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

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

问题描述

这是课程:

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天全站免登陆