1

I need to "wrap" C# methods to set and initialize variables. The wrapper has to do something BEFORE and AFTER the wrapped method. Just as a basic example, I'd like to do something like:

public void foo()
{
 Console.WriteLine("inside foo");
}

public void silly_wrapper(string ham)
{
 // somethig before
 Console.WriteLine(ham + "before" );
 DateTime tic = DateTime.Now; //Current Date

 // call function
 foo();

 // something after
 TimeSpan time = DateTime.Now - tic; //Current Date
 Console.WriteLine(ham + $"after in {time}");
}

I have to repeat this on almost ALL my methods. Actually I want to call an Initialize() method after all the constructors of all the classes in my project.

Is there any way to do it in a smarter way? I've tried to implement Attribute but there is no way to call something after the method.

[mywrapperFunction("spam")]
public void foo()
{
 Console.WriteLine("inside foo");
} 

Generalizing the wrapper with a Func argument is going to be a mess (too many options) and I'm supposed to call every function inside the wrapper function.

Dario
  • 13
  • 5
  • 1
    "but there is no way to call something after the method." Huum? How you implement that attribute is completely up to you, of course you can imple,ent it to execute your method in the middle. – MakePeaceGreatAgain Jun 15 '22 at 08:04
  • 2
    Have you thought about the [Decorator pattern](https://refactoring.guru/design-patterns/decorator)? – Lukas Hein Jun 15 '22 at 08:07
  • It __seems to me__ that `Attribute` can add info, do something before [creating-custom-attributes](https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/attributes/creating-custom-attributes). If there is a way, I have not found any example. – Dario Jun 15 '22 at 08:11
  • The answer in the dupe clearly contains both, a pre- and a post-action: `// now first invoke the pre-action method method1.Invoke(null, null); // the actual action action(); // the post-action method2.Invoke(null, null);` – MakePeaceGreatAgain Jun 15 '22 at 08:23
  • But every time I need to call a method, I need to call it wrapped `engine.Execute(m.mymethod);` that is not so the best. It would be better to have a python style "decorator" on `m.mymethod` that "wrap" every call instead of relying on my memory ... that is not good! ;-) – Dario Jun 15 '22 at 17:18
  • @Dario - You need to look up Aspect Oriented Programming (AOP) https://en.wikipedia.org/wiki/Aspect-oriented_programming in C#. Or, potentially, dependency injection with the decorator pattern as an alternative to AOP. Either way, it's hard. You should rely on your memory. – Enigmativity Jun 15 '22 at 22:34
  • Yeah, AOP is your friend. For example see [MethodBoundaryAspect.Fody](https://github.com/vescon/MethodBoundaryAspect.Fody), [MethodDecorator](https://github.com/Fody/MethodDecorator) – Alexander Petrov Jun 15 '22 at 22:39

1 Answers1

1

You need to look up Aspect Oriented Programming (AOP) en.wikipedia.org/wiki/Aspect-oriented_programming in C#. Or, potentially, dependency injection with the decorator pattern as an alternative to AOP. Either way, it's hard. You should rely on your memory.

However, a simple approach that may work for you is this:

public static class Wrapper
{
    public static void Call(string ham, Action action)
    {
        Console.WriteLine(ham + "before");
        var sw = Stopwatch.StartNew();
        action();
        sw.Stop();
        Console.WriteLine(ham + $"after in {sw.Elapsed}");
    }
    public static T Call<T>(string ham, Func<T> func)
    {
        Console.WriteLine(ham + "before");
        var sw = Stopwatch.StartNew();
        var t = func();
        sw.Stop();
        Console.WriteLine(ham + $"after in {sw.Elapsed}");
        return t;
    }
}

Now you'd still have to remember, but your code now looks like this:

Wrapper.Call("Inside foo", foo);
Enigmativity
  • 113,464
  • 11
  • 89
  • 172