方法缺少C#4.0中的困难:动态与RealProxy

Tho*_*hom 6 c# proxy dynamic method-missing c#-4.0

有没有人知道一种方法来拦截dynamic方法调用(特别是那些将要提升RuntimeBinderExceptions的方法)RealProxy?我希望捕获异常并在其上实现'方法缺失',但它似乎在拦截器获得查看之前被抛出.

我的测试看起来像:

dynamic hello = MethodMissingInterceptor<DynamicObject>.Create();
Assert.AreEqual("World", hello.World());
Run Code Online (Sandbox Code Playgroud)

哪里World没有实际实施DynamicObject.拦截器是非常简单的-我希望检查IMethodReturnMessage.ExceptionRuntimeBinderException,并转发到是这样的:

public IMessage MethodMissing(IMethodCallMessage call)
{
    return new ReturnMessage(call.MethodBase.Name, new object[0], 0, call.LogicalCallContext, call);
}
Run Code Online (Sandbox Code Playgroud)

不幸的是,我在拦截器中看到的只是一些调用GetType,而不是不存在的World方法.

失败了 - 有没有人知道是否有一个DynamicProxy版本在.NET 4.0上运行得很快但可能解决了这个问题?

Chr*_*ows 17

我将从长篇大论开始.C#中动态操作的每个绑定按此顺序执行大约这三项操作:

  1. 如果它实现了IDynamicMetaObjectProvider或者是一个COM对象,请让对象绑定自己,如果失败,那么......
  2. 使用反射将操作绑定到plain-old-clr-object上的操作,如果失败,则...
  3. 返回表示完全失败的DynamicMetaObject.

您正在看到GetType调用,因为在第2步中,C#运行时绑定器正在反映您,以尝试确定您是否有适合调用的"World"方法,并且这种情况正在发生,因为IDLOMetaObjectProvider实现了hello,如果有的话,无法想出任何特别的事情.

不幸的是,在抛出RuntimeBinderException时,我们不再绑定了.异常来自动态操作的执行阶段,以响应由于步骤3返回的元对象.您唯一有机会捕获它是在实际的调用站点.

如果你想在C#中实现method_missing,那么这个策略对你来说不会有用.你确实有一些选择.

一个简单的选择是在MethodMissingInterceptor中实现IDynamicMetaObjectProvider,并遵循包装对象的IDMOP实现.如果内部IDMOP出现故障,您可以绑定到您想要的任何内容(可能是对存储在拦截器中的method_missing委托的调用).这里的缺点是,这仅适用于已知为动态对象的对象,例如那些以IDMOP开头的对象.这是因为您基本上是在步骤1和2之间插入自己.

我能想到的另一个替代方案是实现IDynamicMetaObjectProvider,并在其中对每个绑定做出积极响应,返回对方法的调用,该方法(a)生成C#编译器首先生成绑定的相同代码,并且( b)捕获RuntimeBinderException以调用method_missing方法.这里的缺点是它会非常复杂 - 你需要生成任意委托类型和使用它们的IL,而不是C#运行时绑定程序集中的公共类型,坦率地说,它不适合公共使用.但至少你会得到针对所有操作的方法.

我确信还有其他一些我没有想过的策略,比如你似乎暗示要使用远程代理.我无法想象它们看起来像什么,我不能说它们是否会成功.

这里问题的关键在于C#4.0没有一种能够预测你想做到这一点的设计.具体来说,你不能轻易地在第2步和第3步之间插入自己.这让我得到简短的回答,很抱歉,C#4.0没有method_missing.