有人知道用RealProxy拦截dynamic方法调用(特别是那些要引发RuntimeBinderException的方法调用)的方法吗?我希望捕获异常并在此之上实现“方法缺失”,但它似乎在拦截器得到查看之前被抛出。
我的测试看起来是这样的:
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方法。
如果失败了--有没有人知道是否有一个在.NET 4.0上快乐运行的DynamicProxy版本可能已经解决了这个问题?
发布于 2009-06-10 00:32:49
我将从冗长的答案开始。C#中的每个动态操作绑定大致按以下顺序完成以下三件事:
如果对象实现了IDynamicMetaObjectProvider或是COM对象,
之所以会看到GetType调用,是因为在第2步中,C#运行时绑定器会反映出您是否有适合调用的"World“方法,而之所以会发生这种情况,是因为hello的IDynamicMetaObjectProvider实现(如果有)无法提供任何特殊的功能。
不幸的是,当抛出RuntimeBinderException时,我们不再绑定。异常出现在动态操作的执行阶段,响应于步骤3返回的元对象。捕获它的唯一机会是在实际的调用站点。
因此,如果您想要在C#中实现method_missing,那么这种策略对您来说是行不通的。不过,您确实有一些选择。
一个简单的选择是在您的MethodMissingInterceptor中实现IDynamicMetaObjectProvider,并遵循包装对象的IDMOP实现。在内部IDMOP失败的情况下,您可以绑定到您想要的任何东西(可能是对存储在拦截器中的method_missing委托的调用)。这里的缺点是,这只适用于已知为动态对象的对象,例如那些一开始实现IDMOP的对象。这是因为您基本上是在步骤1和步骤2之间插入自己。
我能想到的另一种选择是实现IDynamicMetaObjectProvider,并且在其中,对每个绑定都做出积极响应,返回对一个方法的调用,该方法(a)生成与C#编译器最初绑定时生成的代码相同的代码,(b)捕获RuntimeBinderException以调用method_missing方法。这里的缺点是它将非常复杂--您需要针对C#运行时绑定器程序集中的公共类型生成任意委托类型和使用它们的IL,坦率地说,这些公共类型不是用于公共消费的。但至少在所有操作中都会缺少方法。
我相信我还没有想过其他的策略,比如你似乎在暗示使用远程代理。我无法想象他们是什么样子,我也不能说他们是否会成功。
问题的症结在于,C# 4.0的设计并不能满足您这样做的愿望。具体来说,你不能很容易地在步骤2和步骤3之间插入自己。这给了我一个简短的答案,很抱歉,C# 4.0没有method_missing。
https://stackoverflow.com/questions/961673
复制相似问题