是否有人知道如何使用dynamic
拦截RuntimeBinderException
方法调用(特别是那些将会RealProxy
提升的方法)?我希望捕获异常并在其上实现'方法缺失',但它似乎在拦截器获得查看之前被抛出。
我的测试看起来像:
dynamic hello = MethodMissingInterceptor<DynamicObject>.Create();
Assert.AreEqual("World", hello.World());
World
实际上未在DynamicObject
上实施IMethodReturnMessage.Exception
。拦截器非常简单 - 我希望检查RuntimeBinderException
public IMessage MethodMissing(IMethodCallMessage call)
{
return new ReturnMessage(call.MethodBase.Name, new object[0], 0, call.LogicalCallContext, call);
}
并转发到类似的东西:
GetType
不幸的是,我在拦截器中看到的只是对World
的一些调用,而不是不存在的DynamicProxy
方法。
失败了 - 有没有人知道是否有一个{{1}}版本在.NET 4.0上运行得很快但可能解决了这个问题?
答案 0 :(得分:17)
我将从冗长的答案开始。 C#中动态操作的每个绑定按以下顺序执行大约这三项操作:
您正在看到GetType调用,因为在第2步中,C#运行时绑定程序正在反映您尝试确定您是否具有适合调用的“World”方法,并且这种情况正在发生,因为IDynamicMetaObjectProvider实现你好,如果有的话,就无法做出任何特别的事情。
不幸的是,在抛出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。