alielie
2026-09-10 f3889f2d36c50cf99468594854def9b7ed069fb5
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
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using DynamicExpresso.Resolution;
 
namespace DynamicExpresso.Reflection
{
    internal class MemberFinder
    {
        private readonly ParserArguments _arguments;
        private readonly BindingFlags _bindingCase;
        private readonly MemberFilter _memberFilterCase;
 
        public MemberFinder(ParserArguments arguments)
        {
            _arguments = arguments;
            _bindingCase = arguments.Settings.CaseInsensitive ? BindingFlags.IgnoreCase : BindingFlags.Default;
            _memberFilterCase = arguments.Settings.CaseInsensitive ? Type.FilterNameIgnoreCase : Type.FilterName;
        }
 
        public MemberInfo FindPropertyOrField(Type type, string memberName, bool staticAccess)
        {
            var flags = BindingFlags.Public | BindingFlags.DeclaredOnly |
                        (staticAccess ? BindingFlags.Static : BindingFlags.Instance) | _bindingCase;
 
            foreach (var t in SelfAndBaseTypes(type))
            {
                var members = t.FindMembers(MemberTypes.Property | MemberTypes.Field, flags, _memberFilterCase, memberName);
                if (members.Length != 0)
                    return members[0];
            }
            return null;
        }
 
        public IList<MethodData> FindMethods(Type type, string methodName, bool staticAccess, Expression[] args)
        {
            var flags = BindingFlags.Public | BindingFlags.DeclaredOnly |
                        (staticAccess ? BindingFlags.Static : BindingFlags.Instance) | _bindingCase;
            foreach (var t in SelfAndBaseTypes(type))
            {
                var members = t.FindMembers(MemberTypes.Method, flags, _memberFilterCase, methodName);
                var applicableMethods = MethodResolution.FindBestMethod(members.Cast<MethodBase>(), args);
 
                if (applicableMethods.Count > 0)
                    return applicableMethods;
            }
 
            return Array.Empty<MethodData>();
        }
 
        // this method is static, because we know that the Invoke method of a delegate always has this exact name
        // and therefore we never need to search for it in case-insensitive mode
        public static MethodBase FindInvokeMethod(Type type)
        {
            var flags = BindingFlags.Public | BindingFlags.DeclaredOnly |
                        BindingFlags.Instance;
            foreach (var t in SelfAndBaseTypes(type))
            {
                var method = t.FindMembers(MemberTypes.Method, flags, Type.FilterName, "Invoke")
                    .Cast<MethodBase>()
                    .SingleOrDefault();
 
                if (method != null)
                    return method;
            }
 
            return null;
        }
 
        public IList<MethodData> FindExtensionMethods(string methodName, Expression[] args)
        {
            var matchMethods = _arguments.GetExtensionMethods(methodName);
 
            return MethodResolution.FindBestMethod(matchMethods, args);
        }
 
        public IList<MethodData> FindIndexer(Type type, Expression[] args)
        {
            foreach (var t in SelfAndBaseTypes(type))
            {
                var members = t.GetDefaultMembers();
                if (members.Length != 0)
                {
                    var methods = members.
                        OfType<PropertyInfo>().
                        Select(p => (MethodData)new IndexerData(p));
 
                    var applicableMethods = MethodResolution.FindBestMethod(methods, args);
                    if (applicableMethods.Count > 0)
                        return applicableMethods;
                }
            }
 
            return Array.Empty<MethodData>();
        }
 
        private static IEnumerable<Type> SelfAndBaseTypes(Type type)
        {
            if (type.IsInterface)
            {
                var types = new List<Type>();
                AddInterface(types, type);
 
                types.Add(typeof(object));
 
                return types;
            }
            return SelfAndBaseClasses(type);
        }
 
        private static IEnumerable<Type> SelfAndBaseClasses(Type type)
        {
            while (type != null)
            {
                yield return type;
                type = type.BaseType;
            }
        }
 
        private static void AddInterface(List<Type> types, Type type)
        {
            if (!types.Contains(type))
            {
                types.Add(type);
                foreach (var t in type.GetInterfaces())
                {
                    AddInterface(types, t);
                }
            }
        }
    }
}