Welcome to mirror list, hosted at ThFree Co, Russian Federation.

ReflectionUtils.cs « Internal « Reactive « System.Reactive.Linq « Source « NET « Rx - github.com/mono/rx.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: effdd08d413c666bd7f8fc76b1a73ac4f12ffcd0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.

using System;
using System.Collections.Generic;
using System.Globalization;
using System.Reflection;

#if HAS_WINRT
using System.Runtime.InteropServices.WindowsRuntime;
#endif

namespace System.Reactive
{
    static class ReflectionUtils
    {
        public static TDelegate CreateDelegate<TDelegate>(object o, MethodInfo method)
        {
#if CRIPPLED_REFLECTION
            return (TDelegate)(object)method.CreateDelegate(typeof(TDelegate), o);
#else
            return (TDelegate)(object)Delegate.CreateDelegate(typeof(TDelegate), o, method);
#endif
        }

        public static Delegate CreateDelegate(Type delegateType, object o, MethodInfo method)
        {
#if CRIPPLED_REFLECTION
            return method.CreateDelegate(delegateType, o);
#else
            return Delegate.CreateDelegate(delegateType, o, method);
#endif
        }

        public static void GetEventMethods<TSender, TEventArgs>(Type targetType, object target, string eventName, out MethodInfo addMethod, out MethodInfo removeMethod, out Type delegateType, out bool isWinRT)
#if !NO_EVENTARGS_CONSTRAINT
            where TEventArgs : EventArgs
#endif
        {
            var e = default(EventInfo);

            if (target == null)
            {
                e = targetType.GetEventEx(eventName, true);
                if (e == null)
                    throw new InvalidOperationException(string.Format(CultureInfo.CurrentCulture, Strings_Linq.COULD_NOT_FIND_STATIC_EVENT, eventName, targetType.FullName));
            }
            else
            {
                e = targetType.GetEventEx(eventName, false);
                if (e == null)
                    throw new InvalidOperationException(string.Format(CultureInfo.CurrentCulture, Strings_Linq.COULD_NOT_FIND_INSTANCE_EVENT, eventName, targetType.FullName));
            }

            addMethod = e.GetAddMethod();
            removeMethod = e.GetRemoveMethod();

            if (addMethod == null)
                throw new InvalidOperationException(Strings_Linq.EVENT_MISSING_ADD_METHOD);
            if (removeMethod == null)
                throw new InvalidOperationException(Strings_Linq.EVENT_MISSING_REMOVE_METHOD);

            var psa = addMethod.GetParameters();
            if (psa.Length != 1)
                throw new InvalidOperationException(Strings_Linq.EVENT_ADD_METHOD_SHOULD_TAKE_ONE_PARAMETER);

            var psr = removeMethod.GetParameters();
            if (psr.Length != 1)
                throw new InvalidOperationException(Strings_Linq.EVENT_REMOVE_METHOD_SHOULD_TAKE_ONE_PARAMETER);

            isWinRT = false;

#if HAS_WINRT
            if (addMethod.ReturnType == typeof(EventRegistrationToken))
            {
                isWinRT = true;

                var pet = psr[0];
                if (pet.ParameterType != typeof(EventRegistrationToken))
                    throw new InvalidOperationException(Strings_Linq.EVENT_WINRT_REMOVE_METHOD_SHOULD_TAKE_ERT);
            }
#endif

            delegateType = psa[0].ParameterType;

            var invokeMethod = delegateType.GetMethod("Invoke");

            var parameters = invokeMethod.GetParameters();

            if (parameters.Length != 2)
                throw new InvalidOperationException(Strings_Linq.EVENT_PATTERN_REQUIRES_TWO_PARAMETERS);

            if (!typeof(TSender).IsAssignableFrom(parameters[0].ParameterType))
                throw new InvalidOperationException(string.Format(CultureInfo.CurrentCulture, Strings_Linq.EVENT_SENDER_NOT_ASSIGNABLE, typeof(TSender).FullName));

            if (!typeof(TEventArgs).IsAssignableFrom(parameters[1].ParameterType))
                throw new InvalidOperationException(string.Format(CultureInfo.CurrentCulture, Strings_Linq.EVENT_ARGS_NOT_ASSIGNABLE, typeof(TEventArgs).FullName));

            if (invokeMethod.ReturnType != typeof(void))
                throw new InvalidOperationException(Strings_Linq.EVENT_MUST_RETURN_VOID);
        }

        public static EventInfo GetEventEx(this Type type, string name, bool isStatic)
        {
#if CRIPPLED_REFLECTION
            // TODO: replace in the future by System.Reflection.RuntimeExtensions extension methods
            var q = new Queue<TypeInfo>();
            q.Enqueue(type.GetTypeInfo());

            while (q.Count > 0)
            {
                var t = q.Dequeue();

                var e = t.GetDeclaredEvent(name);
                if (e != null)
                    return e;

                foreach (var i in t.ImplementedInterfaces)
                    q.Enqueue(i.GetTypeInfo());

                if (t.BaseType != null)
                    q.Enqueue(t.BaseType.GetTypeInfo());
            }

            return null;
#else
            return type.GetEvent(name, isStatic ? BindingFlags.Public | BindingFlags.Static : BindingFlags.Public | BindingFlags.Instance);
#endif
        }

#if CRIPPLED_REFLECTION
        public static MethodInfo GetMethod(this Type type, string name)
        {
            return type.GetTypeInfo().GetDeclaredMethod(name);
        }

        public static MethodInfo GetAddMethod(this EventInfo eventInfo)
        {
            return eventInfo.AddMethod;
        }

        public static MethodInfo GetRemoveMethod(this EventInfo eventInfo)
        {
            return eventInfo.RemoveMethod;
        }

        public static bool IsAssignableFrom(this Type type1, Type type2)
        {
            return type1.GetTypeInfo().IsAssignableFrom(type2.GetTypeInfo());
        }
#endif
    }
}