C # Changing a class method at runtime

I need to extend the behavior of an instance, but I do not have access to the source code for this instance. For instance:

/* I don't have the source code for this class, only the runtime instance */ Class AB { public void execute(); } 

in my code, I would intercept every call to execute, compute some sutff, and then call the original execute, something like

 /* This is how I would like to modify the method invokation */ SomeType m_OrgExecute; { AB a = new AB(); m_OrgExecute = GetByReflection( a.execute ); a.execute = MyExecute; } void MyExecute() { System.Console.Writeln( "In MyExecute" ); m_OrgExecute(); } 

Is it possible?

Does anyone have a solution to this problem?

+4
source share
10 answers

Looks like you want a Decorator template .

 class AB { public void execute() {...} } class FlaviosABDecorator : AB { AB decoratoredAB; public FlaviosABDecorator (AB decorated) { this.decoratedAB = decorated; } public void execute() { FlaviosExecute(); //execute your code first... decoratedAB.execute(); } void FlaviosExecute() {...} } 

Then you have to change the code that uses the AB object.

 //original code //AB someAB = new AB(); //new code AB originalAB = new AB(); AB someAB = new FlaviosABDecorotor(originalAB); /* now the following code "just works" but adds your method call */ 
+5
source

I would look at PostSharp. It can “reprogram” existing compiled assemblies to add the look before and after the processing you are looking for. I am not 100% sure that it will meet your needs, but it is very good.

http://www.sharpcrafters.com/aop.net

+2
source

It is not possible to do this directly through reflection, etc.

In order for your own code to be introduced in this way, you need to create a modified version of your assembly and use some form of code injection . You cannot just “change the method” of an arbitrary assembly at runtime.

+2
source

You can use a dynamic proxy server, such as Proxy Lock .

+2
source

Because I prefer composition over inheritance (and because inheritance cannot be an option if the class is sealed), I would wrap AB in my class called FlaviosAB , like this ...

 public class FlaviosAB { private AB _passThrough; public FlaviosAB(){ _passThrough = new AB(); } public void execute() { //Your code... Console.WriteLine("In My Execute"); //Then call the passThrough execute. _passThrough.execute(); } } 
+1
source

if AB is not sealed, then you can inherit the class and override the method. in this case with a new

 class ABChild : AB { public new void execute() { System.Console.Writeln( "In MyExecute" ); } } 

According to the comments, you should call this new method in the ABChild class:

 void Invoke() { ABChild a = new ABChild(); a.execute(); } 

Hope this helps!

0
source

You can always inherit from a class and override the execute () method (if the class is not sealed and the method is not private at least.)

0
source

You can use a wrapper class:

 Class ABWrapper { private AB m_AB; ABWrapper( AB ab ) { m_AB = new AB(); } public void execute() { // Do your stuff, then call original method m_AB.execute(); } } 

This is a good approach when AB implements an interface (you haven't mentioned this though). In this case, ABWrapper must implement the same interface. When you use factory injection or even dependencies to create AB instances, you can easily replace them with your shell.

0
source

You can implement a dynamic proxy. More info here

Basically, you extend the base class and override some of your methods. Now you need to reassign the object called by your instance, and all calls will go through your object first.

0
source

Perhaps one of the AOP-oriented programming (AOP) solutions from this fooobar.com/questions/177706 / ... comes in handy ...

0
source

Source: https://habr.com/ru/post/1308681/


All Articles