我正在尝试确定某个方法是否由async
方法调用。
This answer(被授予,描述了一些不同的情况)建议使用CallerMemberName
属性来查找调用方法的名称。实际上,我的方法的签名看起来像这样:
public void LogCallAsync([CallerMemberName] string caller = "", params object[] parameters)
如果您正在执行类似
的操作,则效果很好logger.LogCallAsync();
如果您有固定数量的参数,它也会很有用。但是,鉴于下一个参数属于params object[]
类型,显然情况并非如此,所以如果您尝试执行类似
logger.LogCallAsync(someObject, someOtherObject)
我会收到编译异常,因为someObject
不是字符串。我尝试了以下解决方法:
logger.LogCallAsync(nameof(CurrentMethod), someObject, someOtherObject);
非常难看。实际上,如果我没有必须这样做,我更喜欢它,所以如果有人在这方面有任何建议会很好,但在我的主要问题上:是有什么方法可以防止人们不正当地打电话?特别是,我想知道是否" CurrentMethod"事实上, 是一种实际的async
方法。
例如,如果我查看StackTrace
的实例,是否有基于此的可靠方法? This article(如果我正确地阅读它)似乎暗示我当前的解决方案(请参阅下面的代码示例)是正确的,但它并不是真正的权威"来源,此时约5岁。
让我展示一个代码示例来说明我现在正试图解决这个问题:
private static void GetCaller()
{
StackTrace stack = new StackTrace();
MethodBase method = stack.GetFrame(1).GetMethod();
Trace.TraceInformation("Method name: " + method.Name);
}
// Some arbitrary async method
private static async Task UseReflection()
{
// Do some kind of work
await Task.Delay(100);
// Figure out who called this method in the first place
// I want some way of figuring out that the UseReflection method is async
GetCaller();
}
static void Main(string[] args)
{
// AsyncPump is basically to make Async work more like it does on a UI application
// See this link: https://blogs.msdn.microsoft.com/pfxteam/2012/01/20/await-synchronizationcontext-and-console-apps/
AsyncPump.Run(async () =>
{
// In this case, it identifies the calling method as "MoveNext"
// Question: in cases like this, will this always be the case (i.e. will it always be MoveNext)?
await UseReflection();
});
// In this case, it identifies the calling method as "Main"
GetCaller();
}
我使用Visual Studio 2015和.NET 4.6来实现它的价值。那么,我的问题是:我可以保证代码总能以类似于我上面的方式工作吗?例如,如果异步方法调用了GetCaller
,那么我总是从堆栈跟踪中获取MoveNext
吗?此外,是否有人知道微软是否在某处提供文件(如果我要求证明我的解决方案能够正常运行)?
编辑:此处的主要用途是记录调用记录器的方法的名称和参数。如果来电者不异步,那么我知道以下代码
StackTrace stack = new StackTrace();
MethodBase method = stack.GetFrame(1).GetMethod();
会告诉我来电者是谁。但是,如果来电者是async
,这显然不会起作用。在这种情况下,我目前正在执行以下操作:
StackTrace st = new StackTrace();
StackFrame callFrame = st.GetFrames().ToList().FirstOrDefault(x => x.GetMethod().Name == caller);
其中caller
是我传递的方法调用的名称,就像我上面列出的签名一样:
public void LogCallAsync([CallerMemberName] string caller = "", params object[] parameters)
显然,效率较低。理论上,我可以为每个记录器调用执行此操作,但这会有点性能损失,如果可能的话,我宁愿避免这种情况。
答案 0 :(得分:2)
是的,所有异步方法都以MoveNext结束。