You need to use some kind of AOP framework. Here is a big list of them.
Let's do an example with the popular Castle.DynamicProxy .
I note right away, we will need to modify the code. Intercepted methods (that is, those methods to which we “add” the TestMethod call) must be virtual. If this is too much of a limitation, you will need another AOP framework (for example, PostSharp ).
Let our code be:
class Program { static void Main(string[] args) { var derived = new Derived(); derived.M3(); } } class Base { public void M1() { Console.WriteLine("Base::M1"); } public int M2(int arg) { Console.WriteLine($"Base::M2, arg = {arg}"); return arg + 1; } } class Derived : Base { public int M3() { Console.WriteLine("Derived::M3"); return M2(10); } }
and test class
class Test { public static void TestMethod(bool entry) { Console.WriteLine($"Test::TestMethod ({(entry ? "in" : "out")})"); } }
We connect via nuget Castle.Core , and we add our interceptor:
using Castle.DynamicProxy; public class Interceptor : IInterceptor { public void Intercept(IInvocation invocation) { Test.TestMethod(); try { invocation.Proceed(); } finally { Test.TestMethod(); } } }
Then (Castle.Proxy restriction) we need to make our classes public and methods virtual. We get this modified code:
public class Base { public virtual void M1() { Console.WriteLine("Base::M1"); } public virtual int M2(int arg) { Console.WriteLine($"Base::M2, arg = {arg}"); return arg + 1; } } public class Derived : Base { public virtual int M3() { Console.WriteLine("Derived::M3"); return M2(10); } }
Change Main :
class Program { static void Main(string[] args) { var i = new Interceptor(); var proxy = new ProxyGenerator().CreateClassProxy<Derived>(i); proxy.M3(); } }
The output of the program:
Test::TestMethod (in) Derived::M3 Test::TestMethod (in) Base::M2, arg = 10 Test::TestMethod (out) Test::TestMethod (out)