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

时间:2010-06-17 14:58:34

标签: c# .net aop dynamic-programming dynamic-proxy

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

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

4 个答案:

答案 0 :(得分:3)

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

我说传统但是因为使用分析器和ENC API,技术上可以更改方法体。但是这些API在受限制的情况下运行,并且不被视为通用API。

答案 1 :(得分:1)

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

答案 2 :(得分:1)

任何好的AOP框架都可以在运行时工作。 我目前正在研究其中一个有这种能力的人。

您可以在此处找到它:NConcern .NET runtime Aspect-Oriented Programming

一个小例子,告诉你它是如何工作的......

假定的自定义属性:

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

标记的classe示例:

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));
}

答案 3 :(得分:-1)

根据您的确切需要,有一些可能性。从.NET 1.0开始,就可以使用System.Runtime.Remoting.Proxies namespace中的类型来拦截调用。