构造.NET表达式以调用动态对象的正确方法

时间:2014-04-19 20:35:53

标签: c# .net dynamic lambda

我需要创建一个调用动态对象的System.Linq.Expressions.Expression。动态对象可以是ExpandoObject或任何其他IDynamicMetaObjectProvider

考虑以下测试:

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());

当myInstance被声明为(仅作为示例)时,我需要创建一个等效表达式:

dynamic myInstance = new ExpandoObject();
myInstance.MyMethod = new Func<string>(() => "hello world");

我想我需要使用Expression.Dynamic方法(参见MSDN)。但我不知道如何使用它。我试图在谷歌搜索,但我发现的唯一例子使用了无法正式使用的Microsoft.CSharp.RuntimeBinder.Binder类(请参阅MSDN):

  

此API支持.NET Framework基础结构,不能直接在您的代码中使用。

使用Microsoft.CSharp.RuntimeBinder.Binder我可以编写以下代码:

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());

这个解决方案是否正确?

2 个答案:

答案 0 :(得分:1)

以下是问题:根据我的理解,没有某种Binder对象进行动态调用没有任何意义。

binder对象表示动态名称解析遵循的规则:

  • 比赛是否区分大小写?
  • 如何解决方法重载?
  • 如果对象是非动态对象该怎么办?
  • 你使用什么后备?

换句话说,Binder对象表示调用“语言”的语义,而IDynamicMetaObjectProvider表示被调用对象的语义。

所以,是的,我们不应该使用CSharp Binder对象。特别是当一些问题发生时,只能通过使用对象的内部来解决这个问题。但是,替代方案只是使用另一个非框架提供的Binder实现。

答案 1 :(得分:-1)

  dynamic x = typeof("<<MethodName>>")
            .GetMethod("ToUniversalTime")
            .Invoke(<<Type Of Object>>, new object[] { [Parameter1,]                    
            [Parameter2,....] }); 

在此代码“类型”中,而不是从哪种类型的对象调用方法...

指定您的方法名称而不是“MethodName”

最后是你的对象而不是“对象类型”

如果没有参数则传递空数组...其他明智的传递而不是“parameter1,2,等等。