2010-06-17 24 views
3

我想拥有属性获取器和方法,我可以使用自己的自定义属性进行修饰,并基于该属性的存在,用不同的实现替换方法体。另外,那个不同的实现需要知道给装饰方法的自定义属性赋予的构造函数参数。如何在运行时替换方法实现?

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

+0

您使用哪种版本的.NET框架?在.NET 4中,您可以使用'dynamic'关键字非常自由地编写动态类。 Theres也是'ExpandoObject',值得一试。 – 2010-06-17 15:06:00

+0

我真的很想拿出一个不局限于框架v4的实现。我希望首先使用它的特定项目是针对.Net v3.5构建的。 – 2010-06-17 15:32:40

+0

[动态替换C#方法的内容?](http:// stackoverflow。com/questions/7299097/dynamic-replace-the-a-c-sharp-method) – user 2016-02-27 17:35:42

回答

3

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

我说传统,但因为使用profiler和ENC APIs,在技术上可以更改方法体。但是这些API在有限的情况下运行,并不被认为是通用API。

+4

但它绝对可以做到。 .Net AOP框架执行这样的修改。 NHibernate动态代理整个类。只是因为没有System.Reflection.Method.ReplaceWith(...)并不意味着我不能做到这一点,没有过多的复杂性,我敢肯定。 – 2010-06-17 15:32:20

+0

@qstarin虽然我不熟悉所有这些框架,但我知道其中的一些框架通过直接修改IL来实现这一点,而不是在执行过程时实现。没有传统的.Net API提供这种功能。 – JaredPar 2010-06-17 15:33:59

+0

hrm ...粘性问题。我不太喜欢AOP的这种做法。 – 2010-06-17 16:24:49

1

存在着几个框架,可以让你在运行时动态改变的任何方法:

  • Prig:免费和开源!
  • Harmony开放源代码和麻省理工学院许可,但.net支持目前似乎不完整。
  • Microsoft Fakes:商业,包含在Visual Studio Premium和Ultimate但不共同体与教师专业
  • Telerik JustMock:商业的,一个 “精简版” 的版本可用
  • Typemock Isolator:商业
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)); 
}