I want to use an attribute on a method to provide information to another method down the call-chain. I do this by examining the stack trace. My experimental results show, that the method carrying the attribute can get inlined and the attribute lost.
I am asking for elegant ways to write code that would add the attribute and at the same time prevent loss of that attribute, even at a cost of not inlining the method carrying the attribute.
I know I could use MethodImpl(MethodImplOptions.NoInlining)
alongside my custom attribute to be safe, but I'd rather not do that, as the attribute is used in many places and it would be "manual coupling" and therefore error-prone.
I don't know if pre-processor macro wouold be elegant solution? Can it be easily shared in the whole project?
In this answer to another question, I found the idea of writing a Roslyn plugin to do this for me. I'd like to avoid that, but it is probably the most elegant solution so far.
I had an idea of my attribute inheriting MethodImpl
, but that's sadly sealed
.
This is my minimal example on which I'm experimenting.
[AttributeUsage(AttributeTargets.Method, Inherited = false, AllowMultiple = true)]
sealed class A : Attribute { }
static void Main(string[] args)
{
M();
}
[A]
static void M()
{
PrintStack();
}
[MethodImpl(MethodImplOptions.NoInlining)]
static void PrintStack()
{
foreach (var frame in new StackTrace().GetFrames())
{
var method = frame.GetMethod();
Console.WriteLine($"{method.Name} ({method.GetCustomAttributes(true).FirstOrDefault()?.GetType().Name})");
}
}
In debug build it prints:
PrintStack ()
M (A)
Main ()
In release build it prints:
PrintStack ()
Main ()
I'm looking for a solution that either preserves the whole M (A)
row or at least just the A
attribute somewhere (maybe at the Main
method).