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

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

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

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

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

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

您可以在此处找到它: NConcer .NET运行时面向方面编程

一个小例子向您展示它是如何工作的……

假定的自定义属性:

 [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 Advise(MethodInfo method) { var myattribute1 = method.GetCustomAttributes(typeof(MyAttribute1), true).Cast().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(method => method.IsDefined(typeof(MyAttribute1), true)); } 

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

  • Prig :自由开源!
  • Harmony Open Source和MIT获得许可,但.net支持目前似乎不完整。
  • Microsoft Fakes :Commercial,包含在Visual Studio Premium和Ultimate中,但不包括社区和专业版
  • Telerik JustMock :商业,“精简”版本可用
  • Typemock隔离器 :商业

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