2013-12-12 32 views
0

这里是类:如何在运行时扩展一个方法?

class Foo 
{ 
    private void Boo() 
    { 
     // Body... 
    } 

    // Other members... 
} 

我需要的是:

  • 在运行时创建一个Foo2类具有所有Foo类成员的副本。
  • Foo2类替换方法由Boo2方法其内容有所变化。
  • 创建一个Foo2的实例并调用Boo2

谢谢你的帮助。

+1

是否可以更改为'保护virtual'嘘的签名? – PMF

+3

你能解释你为什么这样做吗?我觉得有一个更好的办法... – James

+0

@PMF最终是的 - 它可以将Boo的签名更改为'受保护的虚拟',但是我实际上正在寻找解决方案,以便不会触摸原始码。 –

回答

1

如果它不是这种框架的主要目的,那么可以在运行时使用.NET AOP框架事件来实现。

如果你的方法不是虚拟的,我会积极研究一个可以处理事件的新事件。

您可以采取NConcern .NET runtime AOP Framework

看看猴子补丁 “方面”:

public class MonkeyPatch : IAspect 
{ 
    static public void Patch(MethodInfo oldMethod, MethodInfo newMethod) 
    { 
     //update monkey patch dictionary 
     MonkeyPatch.m_Dictionary[oldMethod] = newMethod; 

     //release previous monkey patch for target method. 
     Aspect.Release<MonkeyPatch>(oldMethod); 

     //weave monkey patch for target method. 
     Aspect.Weave<MonkeyPatch>(oldMethod); 
    } 

    static private Dictionary<MethodInfo, MethodInfo> m_Dictionary = new Dictionary<MethodInfo, MethodInfo>(); 

    public IEnumerable<IAdvice> Advise(MethodInfo method) 
    { 
     if (MonkeyPatch.m_Dictionary.ContainsKey(_Method)) 
     { 
      yield return Advice(MonkeyPatch.m_Dictionary[_Method]); 
     } 
    } 
} 

补丁:

static public void main(string[] args) 
{ 
    //create Boo2, a dynamic method with Boo signature. 
    var boo2 = new DynamicMethod("Boo2", typeof(void), new Type[] { typeof(Foo) }, typeof(Foo), true); 
    var body = boo2.GetILGenerator(); 

    //Fill your ILGenerator... 
    body.Emit(OpCodes.Ret); 

    //Apply the patch 
    MonkeyPatch.Patch(typeof(Foo).GetMethod("Boo"), boo2); 
} 

在第二另一方面,如果你只需要调用的东西原来的电话后,你是在AOP的目标,你可以这样做...

观察看点:

public class Observation : IAspect 
{ 
    static public void Observe(MethodInfo method, Action action) 
    { 
     //update observation dictionary 
     Observation.m_Dictionary[method] = action; 

     //release observation aspect for target method 
     Aspect.Release<Observation>(method); 

     //weave observation aspect for target method. 
     Aspect.Weave<Observation>(method); 
    } 

    static private Dictionary<MethodInfo, Action> m_Dictionary = new Dictionary<MethodInfo, Action>; 

    public IEnumerable<IAdvice> Advice(MethodInfo method) 
    { 
     if (Observation.m_Dictionary.ContainsKey(method)) 
     { 
      yield return Advice.Basic.After(Observation.m_Dictionary[method]); 
     } 
    } 
} 

使用案例:

static public void main(string[] args) 
{ 
    Observation.Observe(typeof(Foo).GetMethod("Boo"),() => { /* paste here your notification code... */ }); 
}