我认为我需要的是被 .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
我需要这个来改变与 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。这段代码只是为了说明我需要什么,不要把它当作食谱,因为它太可怕了。