Search code examples
c#compilationsyntactic-sugar

Is there a way to automatically add wrapper code to all public functions of a class?


I have a C# class. (Note that this is just to illustrate the problem. The real-world code is more complex than this.)

class MyClass
{
    private readonly MyCustomData myData = new MyCustomData();
    private int flarnCount = 0;
    /* Redacted more data structures. */

    public string One                             => myData[1];
    public List<string> Evens                     => myData.Where(item => item.Key % 2 == 0).Select(item => item.Value).ToList();
    public void SetValue(int index, string value) => myData[index] = value;
    public void Flarn()                            { flarnCount+=1; myData[flarnCount] += 12; }

    /* Redacted several hundred other similar functions. */
}

It works great, except I want to be able to call it from multiple threads. No problem, I just add a line...

private readonly object mon = new object();

.. and add a lock(mon) command to each public function.

And this is the problem. I could copy-and-paste that lock command into each of the several hundred public functions, but that seems like hard work and the end result would look really ugly.

Is there a way I can tell the compiler to include the same wrapper inside all public functions?

UPDATE - I could have equally asked how to add the same try/catch block to all public functions. Please don't get hung up on the locking problem itself which is just there to illustrate the problem.


Solution

  • No. Not within the confines of the C# language or compiler.

    If you want to automatically add this wrapper, you could use some refactoring tool or preprocessor, essentially solve the problem at the level of "source code and text processing" rather than using the compiler.

    There are plenty of downsides to that approach. Personally I would be tempted to just copy-paste the wrapper into the 10 classes and call it a day.

    [edit]

    An approach perhaps more idiomatic for C# specifically would be to apply the "decorator" design pattern: https://refactoring.guru/design-patterns/decorator