Как заменить реализацию метода во время выполнения? - PullRequest
3 голосов
/ 17 июня 2010

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

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

Ответы [ 4 ]

3 голосов
/ 17 июня 2010

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

Хотя я говорю «традиционный», потому что с помощью профилировщика и API ENC технически возможно изменить тела методов. Но эти API работают в стесненных обстоятельствах и не рассматриваются как API общего назначения.

1 голос
/ 09 декабря 2016

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

Вы можете найти его здесь: Аспектно-ориентированное программирование во время выполнения NNET.

Небольшой пример, чтобы показать вам, как это работает ...

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

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

Пример помеченного класса:

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

1 голос
/ 07 декабря 2016

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

  • Prig : бесплатный и открытый исходный код!
  • Harmony Open Source и MIT лицензированы, но поддержка .net на данный момент кажется неполной.
  • Microsoft Fakes : коммерческая, включена в Visual Studio Premium и Ultimate, но не сообществои Professional
  • Telerik JustMock : коммерческая, "облегченная" версия доступна
  • Typemock Isolator : коммерческая
0 голосов
/ 21 ноября 2013

Есть несколько возможностей, в зависимости от ваших конкретных потребностей.Начиная с .NET 1.0 стало возможным перехватывать вызовы, используя типы в пространстве имен System.Runtime.Remoting.Proxies .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...