Skip to content

Commit 54a58ca

Browse files
committed
Introduce MemberFinder
1 parent fb4ada0 commit 54a58ca

File tree

2 files changed

+145
-125
lines changed

2 files changed

+145
-125
lines changed

src/DynamicExpresso.Core/Parsing/Parser.cs

+13-125
Original file line numberDiff line numberDiff line change
@@ -49,17 +49,15 @@ public static Expression Parse(ParserArguments arguments)
4949
private char _parseChar;
5050
private Token _token;
5151

52-
private readonly BindingFlags _bindingCase;
53-
private readonly MemberFilter _memberFilterCase;
52+
private readonly MemberFinder _memberFinder;
5453

5554
private readonly DefaultNumberType _defaultNumberType;
5655

5756
private Parser(ParserArguments arguments)
5857
{
5958
_arguments = arguments;
6059

61-
_bindingCase = arguments.Settings.CaseInsensitive ? BindingFlags.IgnoreCase : BindingFlags.Default;
62-
_memberFilterCase = arguments.Settings.CaseInsensitive ? Type.FilterNameIgnoreCase : Type.FilterName;
60+
_memberFinder = new MemberFinder(arguments);
6361

6462
_defaultNumberType = arguments.Settings.DefaultNumberType;
6563

@@ -667,7 +665,7 @@ private MethodData FindUnaryOperator(string operatorName, Expression expr)
667665
var args = new[] { expr };
668666

669667
// try to find the user defined operator on both operands
670-
var applicableMethods = FindMethods(type, operatorName, true, args);
668+
var applicableMethods = _memberFinder.FindMethods(type, operatorName, true, args);
671669
if (applicableMethods.Length > 1)
672670
throw ParseException.Create(errorPos, ErrorMessages.AmbiguousUnaryOperatorInvocation, operatorName, TypeUtils.GetTypeName(type));
673671

@@ -1253,7 +1251,7 @@ private void ParsePossibleMemberBinding(Type newType, int originalPos, List<Memb
12531251
ValidateToken(TokenId.Identifier, ErrorMessages.IdentifierExpected);
12541252

12551253
var propertyOrFieldName = _token.text;
1256-
var member = FindPropertyOrField(newType, propertyOrFieldName, false);
1254+
var member = _memberFinder.FindPropertyOrField(newType, propertyOrFieldName, false);
12571255
var pos = _token.pos;
12581256
if (allowCollectionInit)
12591257
{
@@ -1352,7 +1350,7 @@ private Expression ParseInvocation(Expression expr, int errorPos, string error)
13521350
{
13531351
var args = ParseArgumentList();
13541352

1355-
var invokeMethod = FindInvokeMethod(expr.Type);
1353+
var invokeMethod = _memberFinder.FindInvokeMethod(expr.Type);
13561354
if (invokeMethod == null || !MethodResolution.CheckIfMethodIsApplicableAndPrepareIt(invokeMethod, args))
13571355
throw ParseException.Create(errorPos, error);
13581356

@@ -1369,7 +1367,7 @@ private Expression ParseMethodGroupInvocation(MethodGroupExpression methodGroup,
13691367
{
13701368
Delegate = _,
13711369
Method = _.Method,
1372-
InvokeMethod = FindInvokeMethod(_.GetType()),
1370+
InvokeMethod = _memberFinder.FindInvokeMethod(_.GetType()),
13731371
})
13741372
.ToList();
13751373

@@ -1657,7 +1655,7 @@ private Expression ParseMemberAccess(Type type, Expression instance)
16571655

16581656
private Expression GeneratePropertyOrFieldExpression(Type type, Expression instance, int errorPos, string propertyOrFieldName)
16591657
{
1660-
var member = FindPropertyOrField(type, propertyOrFieldName, instance == null);
1658+
var member = _memberFinder.FindPropertyOrField(type, propertyOrFieldName, instance == null);
16611659
if (member != null)
16621660
{
16631661
return member is PropertyInfo ?
@@ -1702,7 +1700,7 @@ private Expression ParseExtensionMethodInvocation(Type type, Expression instance
17021700
extensionMethodsArguments[0] = instance;
17031701
args.CopyTo(extensionMethodsArguments, 1);
17041702

1705-
var extensionMethods = FindExtensionMethods(id, extensionMethodsArguments);
1703+
var extensionMethods = _memberFinder.FindExtensionMethods(id, extensionMethodsArguments);
17061704
if (extensionMethods.Length > 1)
17071705
throw ParseException.Create(errorPos, ErrorMessages.AmbiguousMethodInvocation, id, TypeUtils.GetTypeName(type));
17081706

@@ -1720,7 +1718,7 @@ private Expression ParseExtensionMethodInvocation(Type type, Expression instance
17201718

17211719
private Expression ParseNormalMethodInvocation(Type type, Expression instance, int errorPos, string id, Expression[] args)
17221720
{
1723-
var applicableMethods = FindMethods(type, id, instance == null, args);
1721+
var applicableMethods = _memberFinder.FindMethods(type, id, instance == null, args);
17241722
if (applicableMethods.Length > 1)
17251723
throw ParseException.Create(errorPos, ErrorMessages.AmbiguousMethodInvocation, id, TypeUtils.GetTypeName(type));
17261724

@@ -1850,7 +1848,7 @@ private Expression ParseElementAccess(Expression expr)
18501848
if (TypeUtils.IsDynamicType(expr.Type) || IsDynamicExpression(expr))
18511849
return ParseDynamicIndex(expr.Type, expr, args);
18521850

1853-
var applicableMethods = FindIndexer(expr.Type, args);
1851+
var applicableMethods = _memberFinder.FindIndexer(expr.Type, args);
18541852
if (applicableMethods.Length == 0)
18551853
{
18561854
throw ParseException.Create(errorPos, ErrorMessages.NoApplicableIndexer,
@@ -1907,122 +1905,13 @@ private void CheckAndPromoteOperands(Type signatures, ref Expression left, ref E
19071905

19081906
private Expression[] PrepareOperandArguments(Type signatures, Expression[] args)
19091907
{
1910-
var applicableMethods = FindMethods(signatures, "F", false, args);
1908+
var applicableMethods = _memberFinder.FindMethods(signatures, "F", false, args);
19111909
if (applicableMethods.Length == 1)
19121910
return applicableMethods[0].PromotedParameters;
19131911

19141912
return args;
19151913
}
19161914

1917-
private MemberInfo FindPropertyOrField(Type type, string memberName, bool staticAccess)
1918-
{
1919-
var flags = BindingFlags.Public | BindingFlags.DeclaredOnly |
1920-
(staticAccess ? BindingFlags.Static : BindingFlags.Instance) | _bindingCase;
1921-
1922-
foreach (var t in SelfAndBaseTypes(type))
1923-
{
1924-
var members = t.FindMembers(MemberTypes.Property | MemberTypes.Field, flags, _memberFilterCase, memberName);
1925-
if (members.Length != 0)
1926-
return members[0];
1927-
}
1928-
return null;
1929-
}
1930-
1931-
private MethodData[] FindMethods(Type type, string methodName, bool staticAccess, Expression[] args)
1932-
{
1933-
var flags = BindingFlags.Public | BindingFlags.DeclaredOnly |
1934-
(staticAccess ? BindingFlags.Static : BindingFlags.Instance) | _bindingCase;
1935-
foreach (var t in SelfAndBaseTypes(type))
1936-
{
1937-
var members = t.FindMembers(MemberTypes.Method, flags, _memberFilterCase, methodName);
1938-
var applicableMethods = MethodResolution.FindBestMethod(members.Cast<MethodBase>(), args);
1939-
1940-
if (applicableMethods.Length > 0)
1941-
return applicableMethods;
1942-
}
1943-
1944-
return new MethodData[0];
1945-
}
1946-
1947-
private MethodData FindInvokeMethod(Type type)
1948-
{
1949-
var flags = BindingFlags.Public | BindingFlags.DeclaredOnly |
1950-
BindingFlags.Instance | _bindingCase;
1951-
foreach (var t in SelfAndBaseTypes(type))
1952-
{
1953-
var method = t.FindMembers(MemberTypes.Method, flags, _memberFilterCase, "Invoke")
1954-
.Cast<MethodBase>()
1955-
.SingleOrDefault();
1956-
1957-
if (method != null)
1958-
return MethodData.Gen(method);
1959-
}
1960-
1961-
return null;
1962-
}
1963-
1964-
private MethodData[] FindExtensionMethods(string methodName, Expression[] args)
1965-
{
1966-
var matchMethods = _arguments.GetExtensionMethods(methodName);
1967-
1968-
return MethodResolution.FindBestMethod(matchMethods, args);
1969-
}
1970-
1971-
private MethodData[] FindIndexer(Type type, Expression[] args)
1972-
{
1973-
foreach (var t in SelfAndBaseTypes(type))
1974-
{
1975-
MemberInfo[] members = t.GetDefaultMembers();
1976-
if (members.Length != 0)
1977-
{
1978-
IEnumerable<MethodData> methods = members.
1979-
OfType<PropertyInfo>().
1980-
Select(p => (MethodData)new IndexerData(p));
1981-
1982-
var applicableMethods = MethodResolution.FindBestMethod(methods, args);
1983-
if (applicableMethods.Length > 0)
1984-
return applicableMethods;
1985-
}
1986-
}
1987-
1988-
return new MethodData[0];
1989-
}
1990-
1991-
private static IEnumerable<Type> SelfAndBaseTypes(Type type)
1992-
{
1993-
if (type.IsInterface)
1994-
{
1995-
var types = new List<Type>();
1996-
AddInterface(types, type);
1997-
1998-
types.Add(typeof(object));
1999-
2000-
return types;
2001-
}
2002-
return SelfAndBaseClasses(type);
2003-
}
2004-
2005-
private static IEnumerable<Type> SelfAndBaseClasses(Type type)
2006-
{
2007-
while (type != null)
2008-
{
2009-
yield return type;
2010-
type = type.BaseType;
2011-
}
2012-
}
2013-
2014-
private static void AddInterface(List<Type> types, Type type)
2015-
{
2016-
if (!types.Contains(type))
2017-
{
2018-
types.Add(type);
2019-
foreach (Type t in type.GetInterfaces())
2020-
{
2021-
AddInterface(types, t);
2022-
}
2023-
}
2024-
}
2025-
20261915
private static bool IsWritable(Expression expression)
20271916
{
20281917
switch (expression.NodeType)
@@ -2042,7 +1931,6 @@ private static bool IsWritable(Expression expression)
20421931
}
20431932
case ExpressionType.Parameter:
20441933
return true;
2045-
20461934
}
20471935

20481936
return false;
@@ -2211,7 +2099,7 @@ private MethodData FindBinaryOperator(string operatorName, Expression left, Expr
22112099
MethodData userDefinedOperator = null;
22122100

22132101
// try to find the user defined operator on both operands
2214-
var opOnLeftType = FindMethods(leftType, operatorName, true, args);
2102+
var opOnLeftType = _memberFinder.FindMethods(leftType, operatorName, true, args);
22152103
if (opOnLeftType.Length > 1)
22162104
throw error;
22172105

@@ -2220,7 +2108,7 @@ private MethodData FindBinaryOperator(string operatorName, Expression left, Expr
22202108

22212109
if (leftType != rightType)
22222110
{
2223-
var opOnRightType = FindMethods(rightType, operatorName, true, args);
2111+
var opOnRightType = _memberFinder.FindMethods(rightType, operatorName, true, args);
22242112
if (opOnRightType.Length > 1)
22252113
throw error;
22262114

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Linq.Expressions;
5+
using System.Reflection;
6+
using DynamicExpresso.Resolution;
7+
8+
namespace DynamicExpresso.Reflection
9+
{
10+
internal class MemberFinder
11+
{
12+
private readonly ParserArguments _arguments;
13+
private readonly BindingFlags _bindingCase;
14+
private readonly MemberFilter _memberFilterCase;
15+
16+
public MemberFinder(ParserArguments arguments)
17+
{
18+
_arguments = arguments;
19+
_bindingCase = arguments.Settings.CaseInsensitive ? BindingFlags.IgnoreCase : BindingFlags.Default;
20+
_memberFilterCase = arguments.Settings.CaseInsensitive ? Type.FilterNameIgnoreCase : Type.FilterName;
21+
}
22+
23+
public MemberInfo FindPropertyOrField(Type type, string memberName, bool staticAccess)
24+
{
25+
var flags = BindingFlags.Public | BindingFlags.DeclaredOnly |
26+
(staticAccess ? BindingFlags.Static : BindingFlags.Instance) | _bindingCase;
27+
28+
foreach (var t in SelfAndBaseTypes(type))
29+
{
30+
var members = t.FindMembers(MemberTypes.Property | MemberTypes.Field, flags, _memberFilterCase, memberName);
31+
if (members.Length != 0)
32+
return members[0];
33+
}
34+
return null;
35+
}
36+
37+
public MethodData[] FindMethods(Type type, string methodName, bool staticAccess, Expression[] args)
38+
{
39+
var flags = BindingFlags.Public | BindingFlags.DeclaredOnly |
40+
(staticAccess ? BindingFlags.Static : BindingFlags.Instance) | _bindingCase;
41+
foreach (var t in SelfAndBaseTypes(type))
42+
{
43+
var members = t.FindMembers(MemberTypes.Method, flags, _memberFilterCase, methodName);
44+
var applicableMethods = MethodResolution.FindBestMethod(members.Cast<MethodBase>(), args);
45+
46+
if (applicableMethods.Length > 0)
47+
return applicableMethods;
48+
}
49+
50+
return new MethodData[0];
51+
}
52+
53+
public MethodData FindInvokeMethod(Type type)
54+
{
55+
var flags = BindingFlags.Public | BindingFlags.DeclaredOnly |
56+
BindingFlags.Instance | _bindingCase;
57+
foreach (var t in SelfAndBaseTypes(type))
58+
{
59+
var method = t.FindMembers(MemberTypes.Method, flags, _memberFilterCase, "Invoke")
60+
.Cast<MethodBase>()
61+
.SingleOrDefault();
62+
63+
if (method != null)
64+
return MethodData.Gen(method);
65+
}
66+
67+
return null;
68+
}
69+
70+
public MethodData[] FindExtensionMethods(string methodName, Expression[] args)
71+
{
72+
var matchMethods = _arguments.GetExtensionMethods(methodName);
73+
74+
return MethodResolution.FindBestMethod(matchMethods, args);
75+
}
76+
77+
public MethodData[] FindIndexer(Type type, Expression[] args)
78+
{
79+
foreach (var t in SelfAndBaseTypes(type))
80+
{
81+
var members = t.GetDefaultMembers();
82+
if (members.Length != 0)
83+
{
84+
var methods = members.
85+
OfType<PropertyInfo>().
86+
Select(p => (MethodData)new IndexerData(p));
87+
88+
var applicableMethods = MethodResolution.FindBestMethod(methods, args);
89+
if (applicableMethods.Length > 0)
90+
return applicableMethods;
91+
}
92+
}
93+
94+
return new MethodData[0];
95+
}
96+
97+
private static IEnumerable<Type> SelfAndBaseTypes(Type type)
98+
{
99+
if (type.IsInterface)
100+
{
101+
var types = new List<Type>();
102+
AddInterface(types, type);
103+
104+
types.Add(typeof(object));
105+
106+
return types;
107+
}
108+
return SelfAndBaseClasses(type);
109+
}
110+
111+
private static IEnumerable<Type> SelfAndBaseClasses(Type type)
112+
{
113+
while (type != null)
114+
{
115+
yield return type;
116+
type = type.BaseType;
117+
}
118+
}
119+
120+
private static void AddInterface(List<Type> types, Type type)
121+
{
122+
if (!types.Contains(type))
123+
{
124+
types.Add(type);
125+
foreach (var t in type.GetInterfaces())
126+
{
127+
AddInterface(types, t);
128+
}
129+
}
130+
}
131+
}
132+
}

0 commit comments

Comments
 (0)