-
Notifications
You must be signed in to change notification settings - Fork 4.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[API Proposal]: Add ability to get Caller MethodInfo from any code at runtime #60759
Comments
I couldn't figure out the best area label to add to this issue. If you have write-permissions please help me learn by adding exactly one area label. |
Tagging subscribers to this area: @buyaa-n Issue DetailsBackground and motivationCurrent speс assumes to use If we want to know caller name, we don't want see constructors (".ctor") as a result (because it's a useless info), we want to know caller Method name (omitting implicit or explicit constructor calls chain!) In scenario below the caller member is empty because of implicit constructor calls. using System;
using System.Runtime.CompilerServices;
class Program
{
static void Main()
{
B b = new();
}
}
public class B : A {}
public class A
{
public A([CallerMemberName] string? value = null)
{
Console.WriteLine(value);
}
} If I have dll with public class I tried this workaround to discover caller member: public A([CallerMemberName] string? value = null)
{
new StackTrace().GetFrames().ToList()
.ForEach(x => Console.WriteLine(x.GetMethod()?.Name))
} resut is:
I don't need ".ctor". I look for Main. Ok. But this works only for sync code. When it comes to async calls - the StackTrace I get doesn't contain a sync caller member ("Main") at all, because the call chain is broken here: using System;
using System.Diagnostics;
using System.Runtime.CompilerServices;
using System.Linq;
using System.Threading.Tasks;
class Program
{
static void Main()
{
Foo().GetAwaiter().GetResult();
}
static async Task Foo()
{
await Task.Delay(100);
B b = new();
}
}
public class B : A {}
public class A
{
public A([CallerMemberName] string? value = null)
{
// in this stackTrace we know nothing about Main
new StackTrace().GetFrames().ToList()
.ForEach(x => Console.WriteLine(x.GetMethod()?.Name));
// here we will see Main:
throw new Exception();
}
} console output is:
There is no "Main" here. Chain is broken. but if we look at thrown Exception output - we can see "Program.Main()". chain isn't broken.
So, It would be great if caller name or caller the second Issue here is that API ProposalMethodInfo mi = CurrentThread.GetCallerMethod(); API UsageMethodInfo mi = CurrentThread.GetCallerMethod(); Alternative DesignsNo response RisksNo response
|
This seems like a subset of dotnet/csharplang#4984 |
I am not sure it is doable in reflection, probably better to be moved to System.Diagnostics? cc @steveharter |
Tagging subscribers to this area: @tommcdon Issue DetailsBackground and motivationCurrent speс assumes to use If we want to know caller name, we don't want see constructors (".ctor") as a result (because it's a useless info), we want to know caller Method name (omitting implicit or explicit constructor calls chain!) In scenario below the caller member is empty because of implicit constructor calls. using System;
using System.Runtime.CompilerServices;
class Program
{
static void Main()
{
B b = new();
}
}
public class B : A {}
public class A
{
public A([CallerMemberName] string? value = null)
{
Console.WriteLine(value);
}
} If I have dll with public class I tried this workaround to discover caller member: public A([CallerMemberName] string? value = null)
{
new StackTrace().GetFrames().ToList()
.ForEach(x => Console.WriteLine(x.GetMethod()?.Name))
} resut is:
I don't need ".ctor". I look for Main. Ok. But this works only for sync code. When it comes to async calls - the StackTrace I get doesn't contain a sync caller member ("Main") at all, because the call chain is broken here: using System;
using System.Diagnostics;
using System.Runtime.CompilerServices;
using System.Linq;
using System.Threading.Tasks;
class Program
{
static void Main()
{
Foo().GetAwaiter().GetResult();
}
static async Task Foo()
{
await Task.Delay(100);
B b = new();
}
}
public class B : A {}
public class A
{
public A([CallerMemberName] string? value = null)
{
// in this stackTrace we know nothing about Main
new StackTrace().GetFrames().ToList()
.ForEach(x => Console.WriteLine(x.GetMethod()?.Name));
// here we will see Main:
throw new Exception();
}
} console output is:
There is no "Main" here. Chain is broken. but if we look at thrown Exception output - we can see "Program.Main()". chain isn't broken.
So, It would be great if caller name or caller the second Issue here is that API ProposalMethodInfo mi = CurrentThread.GetCallerMethod();
//or
MethodInfo mi = MethodBase.GetCallerMethod(); API UsageMethodInfo mi = CurrentThread.GetCallerMethod();
//or
MethodInfo mi = MethodBase.GetCallerMethod(); Alternative DesignsNo response RisksNo response
|
Just to add here, I agree with @buyaa-n that this API wouldn't belong on System.Reflection MethodInfo as MethodInfo is just an object that represents the pointer to a method and has info that are not related to current execution. Perhaps this kind of API would be better placed in a type like StackTrace? |
Background and motivation
Current speс assumes to use
CallerMemberName
attribute to know caller name.But this require to write a lot of excessive/garbage code, and do not cover all situations. And this sometimes results in ".ctor" values which is useless.
If we want to know caller name, we don't want see constructors (".ctor") as a result (because it's a useless info), we want to know caller Method name (omitting implicit or explicit constructor calls chain!)
In scenario below the caller member is empty because of implicit constructor calls.
If I have dll with public class
A
which relies onCallerMemberName
attribute in it's constructor - it won't work because I can't control how descendant classes are defined.I tried this workaround to discover caller member:
resut is:
I don't need ".ctor". I look for Main. Ok.
But this works only for sync code. When it comes to async calls - the StackTrace I get doesn't contain a sync caller member ("Main") at all, because the call chain is broken here:
console output is:
There is no "Main" here. Chain is broken.
but if we look at thrown Exception output - we can see "Program.Main()". chain isn't broken.
So,
It would be great if caller name or caller
MethodInfo
(omit constructors! they are useless) to be stored somewhere inExecutionContext
when it's captured, and to be able to get this info somehow from sync or async code. To get it I want to callCurrentThread.CallerMemberName
or something likeCurrentThread.GetCallerMethod()
. It'll look for callers in current thread (if async code), -> if not found -> Look for it inExecutionContext
the second Issue here is that
new StackTrace()
doesn't contain a frames with sync code, from which async code is called.API Proposal
API Usage
Alternative Designs
No response
Risks
No response
The text was updated successfully, but these errors were encountered: