我认为我需要的是 .net 人们称之为“透明动态代理”的东西,但到目前为止我所看到的所有实现(Castle DynamicProxy、Spring.NET AOP 等)都要求我至少执行以下操作之一:
- 将拦截的方法声明为虚拟方法
- 包装类并创建包装器的实例而不是包装类
- 更改继承或实现接口
显然,如果调用者和被调用者都是非虚拟的并且来自第三方闭源库(这种情况),我无能为力。
如果 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 http://www.pcreview.co.uk/forums/overriding-non-virtual-methods-using-il-and-reflection-emit-t2605695.html)
- 联系创建该库的公司(他们不再支持该产品)
- 停止使用该库或使用替代方案(不可能,因为它是我们所依赖的 RAD IDE 运行时的一部分,因为有大量使用 IDE 自己的语言编写的代码)
- 控制对有问题的方法的调用以避免错误(我们已经这样做了,但并没有完全解决问题)
你还有其他想法吗?
PS:抱歉我的英语不好。另外,对不起我的Python。这段代码在这里只是为了说明我需要什么,不要把它当作一个食谱,因为它很糟糕。