zne*_*eak 18 .net c# dynamic-language-runtime
当我想在C#中的任何对象上动态调用静态定义的(在"编译时确定"意义上的"静态",而不是"类级别成员"意义上的)方法时,我可以使用反射来获取该方法的句柄并调用它:
typeof(Foo).GetMethod("Bar").Invoke(foo, new object[] { /* params */ });
Run Code Online (Sandbox Code Playgroud)
但是,通过继承DynamicObject响应(未定义的)实例方法调用而使对象变为TryInvokeMember动态,并且由于显而易见的原因,类不响应的动态方法不会通过反射公开.这意味着我无法获得应该响应的方法的方法句柄TryInvokeMember.
具有讽刺意味的是,在我看来,您无法dynamic像在非dynamic对象上调用已定义的方法那样轻松地动态调用对象上的动态方法.
我考虑过TryInvokeMember直接调用,但第一个参数必须是InvokeMemberBinder一个抽象类的实例.我觉得如果我必须实现一个类来调用动态对象的动态方法,我一定是做错了.
如何dynamic通过名称调用对象上的方法,知道目标类没有实现它并且应该响应使用它TryInvokeMember?
jbt*_*ule 14
我有一个开源(Apache许可证)框架Dynamitey(在nuget中可用),它封装了动态绑定器代码,这包括自动缓存调用站点.它也为每种类型的绑定器提供便利方法(getter,setter,事件,索引器,操作符,转换),但特别是你想要InvokeMember.
当调用静态定义(在编译时)类的成员时,动态绑定器代码实际上比反射(摊销)运行得更快.
Dynamic.InvokeMember(foo,"Bar",arg...);
Run Code Online (Sandbox Code Playgroud)
解决这个问题的一种方法是模仿C#编译器为动态对象上的方法调用输出的内容.这需要一堆标注类型的使用[EditorBrowsable(EditorBrowsableState.Never)]的Microsoft.CSharp.RuntimeBinder命名空间,所以在智能感知,他们将不可见.毋庸置疑,这似乎不是支持的方案,因此使用它需要您自担风险!
此代码调用动态Bar方法,而不会在派生自DynamicObject以下类的类的实例上生成任何参数:
dynamic dynamicObject = new DerivedFromDynamicObject();
var callSiteBinder = Binder.InvokeMember(CSharpBinderFlags.None, "Bar", Enumerable.Empty<Type>(), typeof(Program),
new[] { CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null) });
var callSite = CallSite<Action<CallSite, object>>.Create(callSiteBinder);
callSite.Target(callSite, dynamicObject);
Run Code Online (Sandbox Code Playgroud)