繁体   English   中英

如何在运行时替换方法实现?

[英]How do I replace a method implementation at runtime?

我想拥有可以用我自己的自定义属性装饰的属性 getter 和方法,并根据该属性的存在用不同的实现替换方法主体。 此外,不同的实现将需要知道赋予自定义属性的构造函数参数,它装饰方法。

这显然可以用 AOP 来完成,比如 PostSharp 或 LinFu,但我想知道是否有一种方法可以做到这一点,而不涉及构建后处理步骤,因为添加这比我更喜欢的项目复杂化。

有几个框架允许您在运行时动态更改任何方法:

  • 和谐免费和开源(麻省理工学院)!
  • Prig :免费和开源 (MIT),需要 Visual Studio 扩展并在启动器下运行程序,自 2017 年以来未更新。
  • Microsoft Fakes :商业版,包含在 Visual Studio Enterprise(旧版本的高级版和旗舰版)中,但不包括社区版和专业版
  • Telerik JustMock :商业版,提供“精简版”版本
  • Typemock 隔离器:商用

使用传统的 .Net API 无法实现这一点。 方法体在编译时是固定的,不能更改。

我说传统是因为使用分析器和 ENC API 在技术上可以更改方法主体。 但这些 API 在受限环境中运行,不被视为通用 API。

任何好的 AOP 框架都可以在运行时工作。 我目前以这种能力在其中之一上工作。

你可以在这里找到它: NConcern .NET 运行时面向方面的编程

一个小例子向你展示它是如何工作的......

假设的自定义属性:

[AttributeUsage(AttributeTargets.Method, AllowMultiple=false, Inherited=true)]
public class MyAttribute1 : Attribute
{
    public string MyAttributeValue;
}

标记类的示例:

public class Calculator
{
    [MyAttribute1(MyAttributeValue="Hello World")]
    public int Add(int a, int b)
    {
        return a + b;
    }
}



public class MyAspect : IAspect
{
    //This code will be executed to create a decorator, not in nominal execution flow (You don't have to stress with performance here)
    public IEnumerable<IAdvice> Advise(MethodInfo method)
    {
        var myattribute1 = method.GetCustomAttributes(typeof(MyAttribute1), true).Cast<MyAttribute1>().SingleOrDefault();

        //If attribute is not defined, do not return an "advice"
        if (myattribute1 == null) { yield break; }

        //Get your attribute property.
        var myattributevalue = myattribute1.MyAttributeValue;

        //define your substitute method
        var signature= new Type[] { method.DeclaringType }.Concat(method.GetParameters().Select(parameter => parameter.Type)).ToArray();
        var dynamicMethod = new DynamicMethod(string.Empty, method.ReturnType, signature, method.DeclaringType, true);
        var body = dynamicMethod.GetILGenerator();

        //TODO : emit your code! maybe use your attribute field value to know what kind of replacement you want to do...
        body.Emit(OpCodes.Ret);

        //define the replacement
        yield return new Advice(dynamicMethod);
    }
}

用例:

static public void main(string[] args)
{
    Aspect.Weave<MyAspect>(method => method.IsDefined(typeof(MyAttribute1), true));
}

有一些可能性,具体取决于您的确切需求。 从 .NET 1.0 开始,就可以使用System.Runtime.Remoting.Proxies 命名空间中的类型拦截调用。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM