Shabloinker
Shabloinker

Reputation: 361

Dynamically wrap the contents of a C# method at run-time instantiation

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.

...
//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#?

Upvotes: 1

Views: 776

Answers (2)

adjan
adjan

Reputation: 13652

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

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

Upvotes: 2

David L
David L

Reputation: 33833

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

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:

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

Upvotes: 2

Related Questions