Dav*_*rdi 5 .net c# lambda dynamic
我需要创建一个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());
Run Code Online (Sandbox Code Playgroud)
我需要在声明myInstance时创建一个等效表达式(仅作为示例):
dynamic myInstance = new ExpandoObject();
myInstance.MyMethod = new Func<string>(() => "hello world");
Run Code Online (Sandbox Code Playgroud)
我想我需要使用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());
Run Code Online (Sandbox Code Playgroud)
这个解决方案对吗?
这里有一个问题:根据我的理解,在没有某种Binder对象的情况下进行动态调用是没有意义的。
活页夹对象表示动态名称解析遵循的规则:
换句话说,Binder对象代表调用“语言”的语义,而IDynamicMetaObjectProvider代表被调用对象的语义。
所以,是的,我们不应该使用 CSharp Binder 对象。尤其是当发生一些只能通过使用对象内部来解决的问题时,这种感觉尤其明显。然而,替代方案只是使用另一个非框架提供的Binder实现。