|
1 | 1 | #if !NET35 && !UAP10_0 && !NETSTANDARD1_3 |
| 2 | +using System.Collections; |
2 | 3 | using System.Collections.Generic; |
3 | 4 | using System.Dynamic; |
4 | 5 | using System.Linq.Expressions; |
|
7 | 8 |
|
8 | 9 | namespace System.Linq.Dynamic.Core |
9 | 10 | { |
10 | | - /// <summary> |
11 | | - /// Based on SqlLinq by dkackman. https://github.com/dkackman/SqlLinq/blob/210b594e37f14061424397368ed750ce547c21e7/License.md |
12 | | - /// </summary> |
13 | 11 | /// <seealso cref="GetMemberBinder" /> |
14 | 12 | internal class DynamicGetMemberBinder : GetMemberBinder |
15 | 13 | { |
16 | | - private static readonly Type IDictionaryType = typeof(IDictionary<string, object>); |
17 | | - private static readonly PropertyInfo Indexer = IDictionaryType.GetProperty("Item"); |
| 14 | + private static readonly MethodInfo DynamicGetMemberMethod = typeof(DynamicGetMemberBinder).GetMethod(nameof(GetDynamicMember)); |
18 | 15 |
|
19 | 16 | public DynamicGetMemberBinder(string name, [CanBeNull] ParsingConfig config) : base(name, !(config?.IsCaseSensitive == true)) |
20 | 17 | { |
21 | 18 | } |
22 | 19 |
|
23 | 20 | public override DynamicMetaObject FallbackGetMember(DynamicMetaObject target, DynamicMetaObject errorSuggestion) |
24 | 21 | { |
25 | | - var dictionary = target.Value as IDictionary<string, object>; |
26 | | - if (dictionary == null) |
27 | | - { |
28 | | - throw new InvalidOperationException("Target object is not an ExpandoObject"); |
29 | | - } |
| 22 | + var instance = Expression.Call( |
| 23 | + DynamicGetMemberMethod, |
| 24 | + target.Expression, |
| 25 | + Expression.Constant(Name), |
| 26 | + Expression.Constant(IgnoreCase)); |
| 27 | + return DynamicMetaObject.Create(target.Value, instance); |
| 28 | + } |
| 29 | + |
| 30 | + public static object GetDynamicMember(object value, string name, bool ignoreCase) |
| 31 | + { |
| 32 | + if (value == null) |
| 33 | + throw new InvalidOperationException(); |
| 34 | + |
| 35 | + if (value is IDictionary<string, object> dict1) |
| 36 | + return dict1[name]; |
| 37 | + |
| 38 | + if (value is IDictionary dict2) |
| 39 | + return dict2[name]; |
30 | 40 |
|
31 | | - var instance = Expression.ConvertChecked(target.Expression, IDictionaryType); |
32 | | - var indexExpression = Expression.MakeIndex(instance, Indexer, new Expression[] { Expression.Constant(Name) }); |
| 41 | + var flags = BindingFlags.Instance | BindingFlags.Public; |
| 42 | + if (ignoreCase) flags |= BindingFlags.IgnoreCase; |
| 43 | + var property = value.GetType().GetProperty(name, flags); |
| 44 | + if (property == null) |
| 45 | + throw new InvalidOperationException(); |
33 | 46 |
|
34 | | - return DynamicMetaObject.Create(dictionary, indexExpression); |
| 47 | + return property.GetValue(value, null); |
35 | 48 | } |
36 | 49 | } |
37 | 50 | } |
|
0 commit comments