代码之家  ›  专栏  ›  技术社区  ›  Thom

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

  •  6
  • Thom  · 技术社区  · 16 年前

    有人知道拦截的方法吗 dynamic 方法调用(特别是那些将引发 RuntimeBinderException s) 带着 RealProxy ? 我希望捕获异常并在此基础上实现“methodmissing”,但它似乎是在拦截器进入之前抛出的。

    我的测试看起来就像:

    dynamic hello = MethodMissingInterceptor<DynamicObject>.Create();
    Assert.AreEqual("World", hello.World());
    

    哪里 World 实际上没有在上实现 DynamicObject . 拦截器非常简单-我希望检查一下 IMethodReturnMessage.Exception 对于 然后再向前看,比如:

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

    不幸的是,我在拦截器中看到的只是对 GetType ,而不是不存在的 世界 方法

    如果失败了-有人知道是否有 DynamicProxy 在.NET4.0上运行得很好的版本,这可能解决了这个问题吗?

    1 回复  |  直到 16 年前
        1
  •  17
  •   Chris Burrows    16 年前

    1. 如果对象实现了IDynamicMetaObjectProvider或是COM对象,则要求对象绑定自身,如果绑定失败,则。。。
    2. 使用反射将操作绑定到普通旧clr对象上的操作,如果失败,则。。。

    您看到GetType调用是因为在第2步中,C#运行时绑定器正在向您反映,试图找出是否有一个适合调用的“World”方法,这是因为hello的IDynamicMetaObjectProvider实现(如果有的话)无法提供任何特殊的操作。

    不幸的是,在抛出RuntimeBinderException时,我们不再绑定。异常来自动态操作的执行阶段,响应于步骤3返回的元对象。你唯一的机会是在实际的通话地点。

    所以,如果您想要实现C中缺少的方法,那么这个策略就不适合您。不过你有一些选择。

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

    我能想到的另一种选择是实现IDynamicMetaObjectProvider,并在其中积极响应每个绑定,返回对一个方法的调用,该方法(a)生成与C#编译器将首先生成的绑定代码相同的代码,(b)捕获RuntimeBinderException以调用一个方法#missing方法。这里的缺点是它会非常复杂——您需要生成任意委托类型和使用它们的IL,而C#runtime binder程序集中的公共类型坦率地说,并不用于公共消费。但至少在所有操作中都会缺少方法。

    我相信我还没有想到其他一些策略,比如你似乎暗示要使用远程代理。我无法想象他们是什么样子,我也不能说他们是否会成功。

    这里问题的症结在于C#4.0没有一个能够预见到您希望这样做的设计。具体来说,您无法轻松地将自己插入步骤2和步骤3之间。这让我想到了一个简短的答案,很抱歉,C#4.0没有缺少方法#。