Как я могу заменить реализацию метода во время выполнения?

StackOverflow https://stackoverflow.com/questions/3062830

Вопрос

Я хотел бы получить имущества и методы, которые я могу украсить с моим собственным пользовательским атрибутом и основываясь на наличии этого атрибута, замените тел метода с другим реализацией. Кроме того, эта другая реализация должна будет знать аргументы конструктора, приведенные пользовательскому атрибуту, где он украшает метод.

Это может быть, очевидно, можно сделать с помощью AOP, например, PostSharp или Linfu, но мне интересно, есть ли способ сделать это, что не связано с шагом обработки после сборки, потому что добавление, которое усложняет проект больше, чем я бы предпочел.

Это было полезно?

Решение

Использование традиционных API .NET нет возможности достичь этого. Тела метода фиксируются при компиляционном времени и не могут быть изменены.

Я говорю традиционные, хотя, потому что с Profiler и API-адресами INT технически можно изменить метод тел. Но эти API работают в ограниченных обстоятельствах и не считаются API общего назначения.

Другие советы

Можно с любыми хорошими рамками AOP, работающей во время выполнения. В настоящее время я работаю над одним из них с этой емкостью.

Вы можете найти это здесь : Nconcern .NET Runtime Aspect-ориентированное программирование

Немного примера, чтобы показать вам, как это работает ...

Предполагаемый пользовательский атрибут:

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

Существует пару рамки, которые позволяют динамически изменять любой метод во время выполнения:

  • Пригород: Свободный и открытый источник!
  • Гармония Открытый исходный код и MIT лицензирован, но .NET Поддержка кажется неполной в данный момент.
  • Microsoft Fakes: Коммерческий, включенный в Visual Studio Premium и Ultimate, но не сообщество и профессионал
  • Telerik Stackmock: Коммерческая версия "Lite" доступна
  • Typemock isolator.: Реклама

Есть некоторые возможности, в зависимости от ваших точных потребностей. С момента .Net 1.0, можно перехватить вызовы, используя типы в System.runtime.remoting.proxies.proxies пространство имен.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top