我需要扩展实例的行为,但我无法访问该实例的原始源代码。例如:
/* I don't have the source code for this class, only the runtime instance */
Class AB
{
public void execute();
}
在我的代码中,我会拦截每次执行的调用,计算一些sutff,然后调用原始执行,类似
/* This is how I would like to modify the method invokation */
SomeType m_OrgExecute;
{
AB a = new AB();
m_OrgExecute = GetByReflection( a.execute );
a.execute = MyExecute;
}
void MyExecute()
{
System.Console.Writeln( "In MyExecute" );
m_OrgExecute();
}
这可能吗?
有没有人能解决这个问题?
答案 0 :(得分:5)
看起来你想要Decorator pattern。
class AB
{
public void execute() {...}
}
class FlaviosABDecorator : AB
{
AB decoratoredAB;
public FlaviosABDecorator (AB decorated)
{
this.decoratedAB = decorated;
}
public void execute()
{
FlaviosExecute(); //execute your code first...
decoratedAB.execute();
}
void FlaviosExecute() {...}
}
然后,您必须修改使用AB
对象的代码。
//original code
//AB someAB = new AB();
//new code
AB originalAB = new AB();
AB someAB = new FlaviosABDecorotor(originalAB);
/* now the following code "just works" but adds your method call */
答案 1 :(得分:3)
没有办法直接通过反射等来做到这一点。
为了让您自己的代码像这样注入,您需要创建其程序集的修改版本,并使用某种形式的code injection。您不能只是在运行时“更改任意程序集的方法”。
答案 2 :(得分:2)
我会看看PostSharp。它可以“重新连接”现有的已编译程序集,以添加您要查找的前后处理类型。我不是百分百肯定它会解决你的需求,但很有可能。
答案 3 :(得分:2)
您可以使用动态代理,例如Castle Proxy。
答案 4 :(得分:1)
因为我喜欢组合而不是继承(并且因为如果密封了类,继承可能不是一个选项),我会将AB
包装在我自己的类FlaviosAB
中,就像这样......
public class FlaviosAB
{
private AB _passThrough;
public FlaviosAB(){
_passThrough = new AB();
}
public void execute()
{
//Your code...
Console.WriteLine("In My Execute");
//Then call the passThrough's execute.
_passThrough.execute();
}
}
答案 5 :(得分:0)
如果AB未密封,则可以继承该类并覆盖该方法。在这种情况下使用新的
class ABChild : AB {
public new void execute() {
System.Console.Writeln( "In MyExecute" );
}
}
根据评论,你应该在ABChild类中调用这个 new 方法:
void Invoke() {
ABChild a = new ABChild();
a.execute();
}
希望它有所帮助!!
答案 6 :(得分:0)
您总是可以从类继承并覆盖execute()方法(如果类没有被密封,并且该方法至少不是私有的。)
答案 7 :(得分:0)
您可以使用包装类:
Class ABWrapper
{
private AB m_AB;
ABWrapper( AB ab )
{
m_AB = new AB();
}
public void execute()
{
// Do your stuff, then call original method
m_AB.execute();
}
}
当AB
实现接口时,这是一个很好的方法(尽管你没有提到)。在这种情况下,ABWrapper
应该实现相同的接口。当您使用 factory 甚至依赖注入创建AB
实例时,您可以使用包装器轻松替换它们。
答案 8 :(得分:0)
您可以实施动态代理。查找更多信息here
基本上,您正在扩展基类并使用您的方法覆盖某些方法。现在您需要重新分配由您的实例调用的对象,并且所有调用将首先通过您的对象。
答案 9 :(得分:0)
也许这个Stackoverflow thread的面向方面编程(AOP)解决方案之一会派上用场......