diff --git a/src/System.Linq.Dynamic.Core/DynamicGetMemberBinder.cs b/src/System.Linq.Dynamic.Core/DynamicGetMemberBinder.cs
index 93adad1d..46be79a9 100644
--- a/src/System.Linq.Dynamic.Core/DynamicGetMemberBinder.cs
+++ b/src/System.Linq.Dynamic.Core/DynamicGetMemberBinder.cs
@@ -1,4 +1,5 @@
#if !NET35 && !UAP10_0 && !NETSTANDARD1_3
+using System.Collections;
using System.Collections.Generic;
using System.Dynamic;
using System.Linq.Expressions;
@@ -7,14 +8,10 @@
namespace System.Linq.Dynamic.Core
{
- ///
- /// Based on SqlLinq by dkackman. https://github.com/dkackman/SqlLinq/blob/210b594e37f14061424397368ed750ce547c21e7/License.md
- ///
///
internal class DynamicGetMemberBinder : GetMemberBinder
{
- private static readonly Type IDictionaryType = typeof(IDictionary);
- private static readonly PropertyInfo Indexer = IDictionaryType.GetProperty("Item");
+ private static readonly MethodInfo DynamicGetMemberMethod = typeof(DynamicGetMemberBinder).GetMethod(nameof(GetDynamicMember));
public DynamicGetMemberBinder(string name, [CanBeNull] ParsingConfig config) : base(name, !(config?.IsCaseSensitive == true))
{
@@ -22,16 +19,32 @@ public DynamicGetMemberBinder(string name, [CanBeNull] ParsingConfig config) : b
public override DynamicMetaObject FallbackGetMember(DynamicMetaObject target, DynamicMetaObject errorSuggestion)
{
- var dictionary = target.Value as IDictionary;
- if (dictionary == null)
- {
- throw new InvalidOperationException("Target object is not an ExpandoObject");
- }
+ var instance = Expression.Call(
+ DynamicGetMemberMethod,
+ target.Expression,
+ Expression.Constant(Name),
+ Expression.Constant(IgnoreCase));
+ return DynamicMetaObject.Create(target.Value, instance);
+ }
+
+ public static object GetDynamicMember(object value, string name, bool ignoreCase)
+ {
+ if (value == null)
+ throw new InvalidOperationException();
+
+ if (value is IDictionary dict1)
+ return dict1[name];
+
+ if (value is IDictionary dict2)
+ return dict2[name];
- var instance = Expression.ConvertChecked(target.Expression, IDictionaryType);
- var indexExpression = Expression.MakeIndex(instance, Indexer, new Expression[] { Expression.Constant(Name) });
+ var flags = BindingFlags.Instance | BindingFlags.Public;
+ if (ignoreCase) flags |= BindingFlags.IgnoreCase;
+ var property = value.GetType().GetProperty(name, flags);
+ if (property == null)
+ throw new InvalidOperationException();
- return DynamicMetaObject.Create(dictionary, indexExpression);
+ return property.GetValue(value, null);
}
}
}
diff --git a/test/System.Linq.Dynamic.Core.Tests/ExpressionTests.cs b/test/System.Linq.Dynamic.Core.Tests/ExpressionTests.cs
index 2f8940f0..9173dfe8 100644
--- a/test/System.Linq.Dynamic.Core.Tests/ExpressionTests.cs
+++ b/test/System.Linq.Dynamic.Core.Tests/ExpressionTests.cs
@@ -1610,12 +1610,12 @@ public void ExpressionTests_OrderBy()
Check.That(qry.OrderBy(x => x.Id).ThenByDescending(x => x.Profile.Age).ToArray()).ContainsExactly(orderBy.ToArray());
}
- //[Fact]
+ [Fact]
public void ExpressionTests_Select_DynamicObjects()
{
// Arrange
dynamic a1 = new { Name = "a", BlogId = 100 };
- dynamic a2 = new { Name = "b", BlogId = 200 };
+ dynamic a2 = new { BlogId = 200, Name = "b" };
var list = new List { a1, a2 };
IQueryable qry = list.AsQueryable();
diff --git a/test/System.Linq.Dynamic.Core.Tests/QueryableTests.Where.cs b/test/System.Linq.Dynamic.Core.Tests/QueryableTests.Where.cs
index f1d7dca3..9369f92d 100644
--- a/test/System.Linq.Dynamic.Core.Tests/QueryableTests.Where.cs
+++ b/test/System.Linq.Dynamic.Core.Tests/QueryableTests.Where.cs
@@ -246,7 +246,7 @@ public void Where_Dynamic_Object_As_Dictionary()
results.Should().HaveCount(1);
}
- [Fact(Skip = "Unable to cast object of type '<>f__AnonymousType35`1[System.String]' to type 'System.Collections.Generic.IDictionary`2[System.String,System.Object]'")]
+ [Fact]
public void Where_Dynamic_ExpandoObject_As_AnonymousType()
{
// Arrange