问题
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:
- Declare intercepted method as virtual
- Wrap class and create instances of the wrapper instead of wrapped class
- Change inheritance or implement interfaces
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.
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
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:
- 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)
Do you have any other idea?
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:
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.
Possible Solution 2:
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.
My recommendation
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.
回答2:
If Bar is static, you might be able to use Moles to detour the method call. Note that this is a pretty heavy-handed approach to fixing the bug and is really not recommended for production code, but it's an option if you're desperate.
来源:https://stackoverflow.com/questions/11763166/how-to-intercept-a-call-to-a-nonvirtual-method-from-to-thirdy-party-libraries-in