【发布时间】:2014-04-19 20:35:52
【问题描述】:
我需要创建一个调用动态对象的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)。但我不知道如何使用它。我曾尝试在 google 上搜索,但我发现的唯一示例使用无法正式使用的 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());
这个解决方案正确吗?
【问题讨论】:
-
是的,这就是我在 CSharpEval 中实现它的方式