在运行时实例化时动态包装C#方法的内容

时间:2021-12-27 03:13:01

I have a base class with some virtual functions

我有一个带有一些虚函数的基类

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

I have another class that inherits from the base class as below.

我有另一个继承自基类的类,如下所示。

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

During run-time I want to instantiate the child class while also wrapping/injecting/overriding a method it overrides in the base class to do as follows. I basically want to add to DoAThing method so that when it is called somewhere else it will do the extra code I added in.

在运行期间,我想实例化子类,同时包装/注入/覆盖它在基类中重写的方法,如下所示。我基本上想要添加到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");
    }
}

Is this possible to do in C#?

这可能在C#中做到吗?

2 个解决方案

#1


2  

You cannot overwrite a method once compiled in C#, unless you dynamically recompile.

除非动态重新编译,否则无法覆盖在C#中编译的方法。

As mentioned in the comments, one possible approach is to use a delegate. You can pass a delegate into an optional constructor and invoke it in DoAThing if it has been passed in:

正如评论中所提到的,一种可能的方法是使用委托。您可以将委托传递给可选构造函数,并在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();
    }
}

In your case, this would be instantiated as:

在您的情况下,这将被实例化为:

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

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

which would fire two additional printed statements when invoked:

这将在调用时触发两个额外的打印语句:

instance.DoAThing();

print this also

打印这个也

child override

儿童覆盖

child override

儿童覆盖

print this base

打印这个基地

#2


2  

An approach closest to what your pseudocode looks like would be adding an Action delegate field to the base class like this:

最接近伪代码的方法是将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();
    }
}

Output:

输出:

child override
print this also
print this base

Since it is a field, you could change the method the delegate points to anytime after instantiation:

由于它是一个字段,您可以在实例化后随时更改委托指向的方法:

instance.DoSomethingExtra = () => Console.WriteLine("new thing");

#1


2  

You cannot overwrite a method once compiled in C#, unless you dynamically recompile.

除非动态重新编译,否则无法覆盖在C#中编译的方法。

As mentioned in the comments, one possible approach is to use a delegate. You can pass a delegate into an optional constructor and invoke it in DoAThing if it has been passed in:

正如评论中所提到的,一种可能的方法是使用委托。您可以将委托传递给可选构造函数,并在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();
    }
}

In your case, this would be instantiated as:

在您的情况下,这将被实例化为:

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

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

which would fire two additional printed statements when invoked:

这将在调用时触发两个额外的打印语句:

instance.DoAThing();

print this also

打印这个也

child override

儿童覆盖

child override

儿童覆盖

print this base

打印这个基地

#2


2  

An approach closest to what your pseudocode looks like would be adding an Action delegate field to the base class like this:

最接近伪代码的方法是将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();
    }
}

Output:

输出:

child override
print this also
print this base

Since it is a field, you could change the method the delegate points to anytime after instantiation:

由于它是一个字段,您可以在实例化后随时更改委托指向的方法:

instance.DoSomethingExtra = () => Console.WriteLine("new thing");