如何在运行时扩展方法? [英] How to extend a method at runtime?

查看:205
本文介绍了如何在运行时扩展方法?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是课程:

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

    // Other members...
}

我需要的是:

  • 在运行时创建一个Foo2类,该类具有所有Foo类成员的副本.
  • Foo2类中,将Boo方法替换为Boo2方法,该方法的内容在一定程度上有所不同.
  • 创建Foo2的实例并调用Boo2.
  • Create a Foo2 class at runtime which has a copy of all Foo class members.
  • In Foo2 class replace Boo method by Boo2 method that has its content alternated to some extent.
  • Create an instance of Foo2 and invoke Boo2.

感谢您的帮助.

推荐答案

如果不是这种框架的主要目的,则可以在运行时使用.NET AOP Framework事件来完成此操作.

You can do it at runtime using a .NET AOP Framework event if it is not the the main purpose of this kind of framework.

如果您的方法不是虚拟的,我将积极研究一种可以处理事件的新方法.

I actively work on a new one which can handle it event if your method is not virtual.

您可以查看 NConcern .NET运行时AOP框架

猴子补丁方面":

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的目标,并且可以这样做...

in the second hand, if you just need to call something after the original call, you are in AOP aim and you can do it like that...

观察方面:

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... */ });
}

这篇关于如何在运行时扩展方法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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