繁体   English   中英

如何拦截来自/到.Net中的第三方库的非虚拟方法的调用?

[英]How to intercept a call to a nonvirtual method from/to thirdy-party libraries in .Net?

我认为我需要的是.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

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

一些(非常不可能工作)的想法:

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

你还有其他想法吗?

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

可能解决方案1:

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

可能的方案2:

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

我的推荐

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM