Динамически оборачивать содержимое метода C # во время выполнения - PullRequest
0 голосов
/ 01 мая 2018

У меня есть базовый класс с некоторыми виртуальными функциями

public class ABaseClass
{
    public virtual void DoAThing()
    {
        print("print this base");
    } 
}

У меня есть другой класс, который наследуется от базового класса, как показано ниже.

public class AChildClass : ABaseClass
{
    public override void DoAThing()
    {
        print("child override");
        base.DoAThing();
    } 
}

Во время выполнения я хочу создать экземпляр дочернего класса, а также обернуть / внедрить / переопределить метод, который он переопределяет в базовом классе, чтобы сделать следующее. Я в основном хочу добавить к DoAThing метод, чтобы при его вызове куда-то еще он делал дополнительный код, который я добавил.

...
//somewhere else I instantiate and override the method at runtime
AChildClass instance = new AChildClass()
{
    DoAThing = new method()
    {
        // Do some extra stuff
        print("print this also");

        // do child class stuff and base stuff
        print("child override")
        base.DoAThing(); //print("print this base");
    }
}

Возможно ли это сделать в C #?

Ответы [ 2 ]

0 голосов
/ 01 мая 2018

Подход, наиболее близкий к тому, как выглядит ваш псевдокод, заключается в добавлении поля делегата Action в базовый класс, например:

public class Program
{
    public static void Main()
    {
        Console.WriteLine("Hello World");
        AChildClass instance = new AChildClass()
        {
            DoSomethingExtra = () => Console.WriteLine("print this also")
        };
        instance.DoAThing();
    }
}

public class ABaseClass
{
    public Action DoSomethingExtra;
    public virtual void DoAThing()
    {
        DoSomethingExtra();
        Console.WriteLine("print this base");
    }
}

public class AChildClass : ABaseClass
{
    public override void DoAThing()
    {
        Console.WriteLine("child override");
        base.DoAThing();
    }
}

Выход:

child override
print this also
print this base

Поскольку это поле, вы можете изменить метод, на который указывает делегат, в любое время после создания экземпляра:

instance.DoSomethingExtra = () => Console.WriteLine("new thing");
0 голосов
/ 01 мая 2018

Вы не можете перезаписать метод, один раз скомпилированный в C #, если вы не перекомпилируете динамически.

Как уже упоминалось в комментариях, одним из возможных подходов является использование делегата. Вы можете передать делегат в необязательный конструктор и вызвать его в DoAThing, если он был передан в:

public class AChildClass : ABaseClass
{
    private readonly Action _doAThing;

    public AChildClass() { }

    public AChildClass(Action doAThing)
    {
        _doAThing = doAThing;
    }

    public override void DoAThing()
    {
        if (_doAThing != null)
        {
            _doAThing();
        }

        print("child override");
        base.DoAThing();
    }
}

В вашем случае это будет выглядеть как:

AChildClass instance = new AChildClass(() => 
{
    // Do some extra stuff
    print("print this also");

    // do child class stuff and base stuff
    print("child override")
});

, который вызовет два дополнительных печатных оператора при вызове:

instance.DoAThing();

распечатайте это также

переопределение дочернего элемента

переопределение дочернего элемента

распечатать эту базу

...