c# - 如何拦截.Net 中第三方库对非虚拟方法的调用?

标签 c# .net reflection disassembly dynamic-proxy

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

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

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

如果 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 以修复此错误。

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

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

你还有别的想法吗?

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

最佳答案

可能的解决方案 1:

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

可能的解决方案 2:

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

我的建议

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

关于c# - 如何拦截.Net 中第三方库对非虚拟方法的调用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11763166/

相关文章:

c# - 正则表达式匹配有效的十六进制字符串但不是全部 '0'

java - 奇怪的Java代码

scala - 如何显示所有类型的对象(Scala中)的?

c# - 从代码发送电子邮件时出现“5.7.1 Client does not have permission”错误

c# - 行为在 Style Setter 中无法正常工作

c# - Xamarin 表单 : How to create a dynamic IMarkupExtension?

.net - T4包含项目根目录中的文件路径

c# - Entity Framework 试图插入错误的表?

c# - Newtonsoft JSON- 与 DataSet 之间的转换会导致 Decimal 变为 Double?

java - "getDeclaredXyz"在Java反射包中代表什么