如何从.Net中的第三方库拦截对非虚拟方法的调用? [英] How to intercept a call to a nonvirtual method from/to thirdy-party libraries in .Net?

查看:131
本文介绍了如何从.Net中的第三方库拦截对非虚拟方法的调用?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我认为我需要的是.net人们所谓的透明动态代理",但是到目前为止,我所见过的所有实现(Castle DynamicProxy,Spring.NET AOP等)都要求我至少执行以下一项操作:这些:

I think what I need is something the .net folks call "transparent dynamic proxy", but all the implementations I've seen this far (Castle DynamicProxy, Spring.NET AOP, etc) require me to do at least one of these:

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

很明显,如果调用方和被调用方都是非虚拟的,并且来自第三方封闭源代码库,那么这种情况将无济于事.

Obviously, if both caller and callee are nonvirtual and from thirdy-party closed source libraries, which is the case, there is nothing I can do.

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

If C# were a dynamic language like Python I would do something like this:

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来修复此错误.

I need this to change a bad behavior of ThirdyPartyLibA.Foo while interacting with ThirdyPartyLibB.Bar. I know exactly what causes this behavior and exactly how to change Foo or Bar to fix this bug thanks to dissasemblers.

一些(很少可行)的想法:

Some (very unlikely to work) ideas:

  • 反汇编ThirdyPartyLibA,更改代码并生成兼容的程序集(由于它是一个强名的程序集,因此无法正常工作)
  • 编辑二进制文件以使Foo的越野车方法虚拟化,并更改使其成为有效程序集所必需的任何内容,以便我可以使用动态代理(由于与上述想法相同的原因,它不太可能起作用)
  • 找到适合的透明动态代理实现(我认为没有基于此论坛主题的实现:
  • Disassemble ThirdyPartyLibA, make changes in code and generate a compatible assembly (unlikely to work because it's a strong-named assembly)
  • Edit binary to make Foo's buggy methods virtual and change whatever is necessary for it to remain a valid assembly so I can use dynamic proxies (very unlikely to work, also because of the same reason as the idea above)
  • Find a transparent dynamic proxy implementation that fits (I think there is none based on this forum thread: http://www.pcreview.co.uk/forums/overriding-non-virtual-methods-using-il-and-reflection-emit-t2605695.html)
  • Contact the company that created the library (they don't support the product anymore)
  • Stop using the library or use an alternative (impossible, since it's part of the runtime of a RAD IDE that we are tied to because there is a HUGE amount of code written using the IDE own language)
  • Control the calls to the problematic methods to avoid the bug (we already did this but it didn't solve the problem completely)

您还有其他想法吗?

PS:对不起,我的英语不好.另外,为我的Python感到抱歉.这段代码只是为了说明我的需要,不要将其当作菜谱,因为它太可怕了.

PS: Sorry for my bad english. Also, sorry for my Python. This code is here just to illustrate what I need, don't take it as a recipe because it's horrible.

推荐答案

可能的解决方案1:

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

Possible Solution 1:

Wrap the library and using a tool like ReSharper to find all usages of the library and replace with the wrapper class. You could also use that opportunity to clean up the presumably crappy interface of the third party library.

虽然 TypeMock 通常用作测试工具,但它将允许您模拟所有内容.因为它将自身作为代码探查器注入,所以您可以嘲笑的东西包括了类的私有和静态成员.另外,任何重写的方法都不需要是虚拟的,因此您可以以这种方式截获调用.

While TypeMock is generally used as a testing tool, it will allow you to mock everything. Because it injects itself as a code profiler, the stuff you can mock included private and static members of classes. As a bonus, any overridden methods do not need to be virtual, so you may be able to intercept the calls that way.

我建议您使用解决方案1.包装程序非常容易理解,它将为您提供一个真正改善代码的好机会.我什至建议您作为一般规则包装第三方库.

I would recommend you go with Solution 1. A wrapper is very easy to understand, and it'll give you a good opportunity to really improve the code. I'd even recommend that you wrap third party libraries as a general rule.

这篇关于如何从.Net中的第三方库拦截对非虚拟方法的调用?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆