4

我认为我需要的是被 .net 人称为“透明动态代理”的东西,但到目前为止我所看到的所有实现(Castle DynamicProxy、Spring.NET AOP 等)都要求我至少执行以下一项操作:

  1. 将拦截的方法声明为虚拟的
  2. 包装类并创建包装器的实例而不是包装类
  3. 更改继承或实现接口

显然,如果调用者和被调用者都是非虚拟的并且来自第三方闭源库,就是这种情况,我无能为力。

如果 C# 是像 Python 这样的动态语言,我会这样做:

foo = ThirdyPartyLibA.Foo()
def interceptor(self, *args, **kwargs):
    do_something_before(self, *args, **kwargs)
    result = ThirdyPartyLibB.Bar.intercepted(self, *args, **kwargs)
    do_something_after(self, result, *args, **kwargs)
    return result
foo.bar.intercepted = interceptor # bar is an instance of ThirdyPartyLibB.Bar
foo.do_its_job() # Foo.do_its_job calls Bar.intercepted

我需要这个来改变与 ThirdyPartyLibB.Bar 交互时 ThirdyPartyLibA.Foo 的不良行为。由于反汇编程序,我确切地知道导致这种行为的原因以及如何更改 Foo 或 Bar 来修复此错误。

一些(不太可能奏效)的想法:

  • 反汇编 ThirdyPartyLibA,更改代码并生成兼容的程序集(不太可能工作,因为它是强名称程序集)
  • 编辑二进制文件以使 Foo 的错误方法虚拟化并更改使其保持有效程序集所需的任何内容,以便我可以使用动态代理(非常不可能工作,也因为与上述想法相同的原因)
  • 找到适合的透明动态代理实现(我认为没有基于此论坛主题:http ://www.pcreview.co.uk/forums/overriding-non-virtual-methods-using-il-and-reflection-发射-t2605695.html )
  • 联系创建库的公司(他们不再支持该产品)
  • 停止使用该库或使用替代方案(不可能,因为它是我们绑定的 RAD IDE 运行时的一部分,因为有大量代码是使用 IDE 自己的语言编写的)
  • 控制对有问题的方法的调用以避免错误(我们已经这样做了,但并没有完全解决问题)

你还有别的想法吗?

PS:对不起我的英语不好。另外,对不起我的 Python。这段代码只是为了说明我需要什么,不要把它当作食谱,因为它太可怕了。

4

2 回答 2

3

可能的解决方案1:

包装库并使用 ReSharper 之类的工具来查找库的所有用法并替换为包装器类。您还可以利用这个机会清理第三方库可能很糟糕的界面。

可能的解决方案2:

虽然TypeMock通常用作测试工具,但它可以让您模拟所有内容。因为它将自己作为代码分析器注入,所以您可以模拟的内容包括类的私有和静态成员。作为奖励,任何重写的方法都不需要是虚拟的,因此您可以通过这种方式拦截调用。

我的推荐

我建议您使用解决方案 1。包装器非常容易理解,它会给您一个真正改进代码的好机会。我什至建议您将第三方库包装为一般规则。

于 2012-08-01T16:17:17.623 回答
1

如果 Bar 是静态的,您也许可以使用Moles绕过方法调用。请注意,这是修复错误的一种非常严厉的方法,实际上不建议用于生产代码,但如果您不顾一切,这是一个选择。

于 2012-08-01T16:10:24.930 回答