我需要创建一个调用动态对象的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());
这个解决方案是否正确?
答案 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,等等。