The task is as follows. There is a separate Test class with the TestMethod method.

public Test { public void TestMethod() { //... } } 

There are also many other classes that inherit from one abstract class and in these classes a large number of methods. In all of these methods, it is necessary that TestMethod () is first called, then the body of the method itself goes and then TestMethod () is called again, that is:

 public Class1:AbstractClass { public void Method1() { TestMethod() //тело метода TestMethod() } public void Method2() { TestMethod() //тело метода TestMethod() } } 

It is clear that you can write this way in each method of each class. But maybe there is a more elegant way to wrap the body methods?

(!!!) Methods can have different input and output parameters. Not only void and without parameters.

  • Yes, methods can have different input and output parameters. - trydex
  • 2
    This is an AOP task. - VladD

2 answers 2

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) 
  • A nightmare ... How can you know all this .... You should ever face it ... - MaximK
  • one
    @MaximK: Yeah, during the work I had to deal with everyone. - VladD

How about using? Although it is not very semantically correct:

 public void Method1(){ using (new TestMethodWrapper()){ //тело метода } } public class TestMethodWrapper : IDisposable { public TestMethodWrapper(){ TestMethod(); } public void Dispose(){ TestMethod(); } }