How do I replace a method implementation at runtime?

a 夏天 提交于 2019-11-28 02:08:15

Using the traditional .Net APIs there is no way to achieve this. Method bodies are fixed at compile time and cannot be changed.

I say traditional though because with the profiler and ENC APIs it's technically possible to change method bodies. But these APIs operate in constrained circumstances and are not considered to be general purpose APIs.

It is possible with any good AOP framework working at runtime. I currently work on one of them with this capacity.

You can find it here : NConcern .NET runtime Aspect-Oriented Programming

A little example to show you how it work...

The supposed custom attribute :

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

Example of a marked 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);
    }
}

Use case :

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

There exists a couple of frameworks that allows you to dynamically change any method at runtime:

  • Prig: Free and Open Source!
  • Harmony Open Source and MIT licensed, but .net support seems to be incomplete at the moment.
  • Microsoft Fakes: Commercial, included in Visual Studio Premium and Ultimate but not Community and Professional
  • Telerik JustMock: Commercial, a "lite" version is available
  • Typemock Isolator: Commercial

There are some possibilities, depending on your exact needs. Ever since .NET 1.0, it has been possible to intercept calls using the the types in the System.Runtime.Remoting.Proxies namespace.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!