Skip to content

Commit

Permalink
Merge branch 'kendarorg-master'
Browse files Browse the repository at this point in the history
  • Loading branch information
davideicardi committed Sep 24, 2016
2 parents 4e34185 + 5295d97 commit fedbb87
Show file tree
Hide file tree
Showing 4 changed files with 113 additions and 73 deletions.
1 change: 1 addition & 0 deletions src/DynamicExpresso.Core/DynamicExpresso.Core.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
<NoWarn>1591</NoWarn>
</PropertyGroup>
<ItemGroup>
<Reference Include="Microsoft.CSharp" />
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
Expand Down
36 changes: 35 additions & 1 deletion src/DynamicExpresso.Core/Parsing/Parser.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
using System;
using Microsoft.CSharp.RuntimeBinder;
using System;
using System.Collections.Generic;
using System.Dynamic;
using System.Globalization;
using System.Linq;
using System.Linq.Expressions;
Expand Down Expand Up @@ -850,8 +852,25 @@ Expression ParseMemberAccess(Type type, Expression instance)
return GeneratePropertyOrFieldExpression(type, instance, errorPos, id);
}

bool IsDynamic(Type type)
{
return type.IsAssignableFrom(typeof(IDynamicMetaObjectProvider)) ||
type.IsAssignableFrom(typeof(ExpandoObject));
}

Expression GeneratePropertyOrFieldExpression(Type type, Expression instance, int errorPos, string propertyOrFieldName)
{
if (IsDynamic(type))
{
var binder = Microsoft.CSharp.RuntimeBinder.Binder.GetMember(
CSharpBinderFlags.None,
propertyOrFieldName,
type,
new[] { CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null) }
);

return Expression.Dynamic(binder, typeof(object), instance);
}
MemberInfo member = FindPropertyOrField(type, propertyOrFieldName, instance == null);
if (member != null)
{
Expand All @@ -867,6 +886,21 @@ Expression ParseMethodInvocation(Type type, Expression instance, int errorPos, s
{
Expression[] args = ParseArgumentList();

if (IsDynamic(type))
{
var argsDynamic = args.ToList();
argsDynamic.Insert(0, instance);
var binderM = Microsoft.CSharp.RuntimeBinder.Binder.InvokeMember(
CSharpBinderFlags.None,
methodName,
null,
type,
argsDynamic.Select(x => CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null))
);

return Expression.Dynamic(binderM, typeof(object), argsDynamic);
}

var methodInvocationExpression = ParseNormalMethodInvocation(type, instance, errorPos, methodName, args);

if (methodInvocationExpression == null && instance != null)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="Microsoft.CSharp" />
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="nunit.framework">
Expand Down
148 changes: 76 additions & 72 deletions test/DynamicExpresso.UnitTest/DynamicTest.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using NUnit.Framework;
using Microsoft.CSharp.RuntimeBinder;
using NUnit.Framework;
using System;
using System.Collections.Generic;
using System.Dynamic;
Expand All @@ -8,75 +9,78 @@

namespace DynamicExpresso.UnitTest
{
// [TestFixture]
// public class DynamicTest
// {
// [Test]
// public void Read_Property_of_an_ExpandoObject()
// {
// dynamic dyn = new ExpandoObject();
// dyn.Foo = "bar";
//
// var interpreter = new Interpreter()
// .SetVariable("dyn", dyn);
//
// Assert.AreEqual(dyn.Foo, interpreter.Eval("dyn.Foo"));
// }
//
// [Test]
// public void Invoke_Method_of_an_ExpandoObject()
// {
// dynamic dyn = new ExpandoObject();
// dyn.Foo = new Func<string>(() => "bar");
//
// var interpreter = new Interpreter()
// .SetVariable("dyn", dyn);
//
// Assert.AreEqual(dyn.Foo(), interpreter.Eval("dyn.Foo()"));
// }
//
// [Test]
// public void Case_Insensitive_Dynamic_Members()
// {
// dynamic dyn = new ExpandoObject();
// dyn.Bar = 10;
//
// var result = new Interpreter()
// .Eval("dyn.BAR", new Parameter("dyn", dyn));
//
// Assert.AreEqual(10, result);
// }
//
// [Test]
// public void Test_With_Standard_Object()
// {
// var myInstance = DateTime.Now;
//
// var methodInfo = myInstance.GetType().GetMethod("ToUniversalTime");
//
// var methodCallExpression = Expression.Call(Expression.Constant(myInstance), methodInfo);
// var expression = Expression.Lambda(methodCallExpression);
//
// Assert.AreEqual(myInstance.ToUniversalTime(), expression.Compile().DynamicInvoke());
// }
//
// [Test]
// public void Test_With_Dynamic_Object()
// {
// dynamic myInstance = new ExpandoObject();
// myInstance.MyMethod = new Func<string>(() => "hello world");
//
// var binder = Binder.InvokeMember(
// CSharpBinderFlags.None,
// "MyMethod",
// null,
// this.GetType(),
// new[] { CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.Constant, null) });
//
// var methodCallExpression = Expression.Dynamic(binder, typeof(object), Expression.Constant(myInstance));
// var expression = Expression.Lambda(methodCallExpression);
//
// Assert.AreEqual(myInstance.MyMethod(), expression.Compile().DynamicInvoke());
// }
// }
[TestFixture]
public class DynamicTest
{
[Test]
public void Read_Property_of_an_ExpandoObject()
{
dynamic dyn = new ExpandoObject();
dyn.Foo = "bar";

var interpreter = new Interpreter()
.SetVariable("dyn", dyn);

Assert.AreEqual(dyn.Foo, interpreter.Eval("dyn.Foo"));
}

[Test]
public void Invoke_Method_of_an_ExpandoObject()
{
dynamic dyn = new ExpandoObject();
dyn.Foo = new Func<string>(() => "bar");

var interpreter = new Interpreter()
.SetVariable("dyn", dyn);

Assert.AreEqual(dyn.Foo(), interpreter.Eval("dyn.Foo()"));
}

[Test]
public void Case_Insensitive_Dynamic_Members()
{
Assert.Throws<RuntimeBinderException>(() =>
{
dynamic dyn = new ExpandoObject();
dyn.Bar = 10;

var result = new Interpreter()
.Eval("dyn.BAR", new Parameter("dyn", dyn));

Assert.AreEqual(10, result);
});
}

[Test]
public void Test_With_Standard_Object()
{
var myInstance = DateTime.Now;

var methodInfo = myInstance.GetType().GetMethod("ToUniversalTime");

var methodCallExpression = Expression.Call(Expression.Constant(myInstance), methodInfo);
var expression = Expression.Lambda(methodCallExpression);

Assert.AreEqual(myInstance.ToUniversalTime(), expression.Compile().DynamicInvoke());
}

[Test]
public void Test_With_Dynamic_Object()
{
dynamic myInstance = new ExpandoObject();
myInstance.MyMethod = new Func<string>(() => "hello world");

var binder = Binder.InvokeMember(
CSharpBinderFlags.None,
"MyMethod",
null,
this.GetType(),
new[] { CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.Constant, null) });

var methodCallExpression = Expression.Dynamic(binder, typeof(object), Expression.Constant(myInstance));
var expression = Expression.Lambda(methodCallExpression);

Assert.AreEqual(myInstance.MyMethod(), expression.Compile().DynamicInvoke());
}
}
}

0 comments on commit fedbb87

Please sign in to comment.