Я пытаюсь определить, был ли вызван конкретный метод методом 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
с трассировкой стека? Кроме того, кто-нибудь знает, если Microsoft документирует это где-нибудь (в случае, если меня попросят доказать, что мое решение будет работать)?
EDIT: Основная цель здесь - записать имя и параметры метода, который называется регистратором. Если вызывающий абонент не асинхронный, то я знаю, что следующий код
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)
Очевидно, что это менее эффективно, , Теоретически я мог бы сделать это для каждого вызова журнала, но это было бы немного хитом производительности, и я предпочел бы избежать этого, если это возможно.
Ваш вопрос имеет [XY Problem] (http://meta.stackexchange.com/questions/66377/what-is-the-xy-problem), написанный на нем. Мне трудно поверить, что полезно каким-либо образом узнать, является ли ваш вызывающий объект фактически методом, объявленным как «async», неважно, возможно. Методы могут выглядеть как «async» -классифицированный метод, фактически не являясь одним из них, а другие методы могут вести себя аналогично методам async (т. Е. Таким образом, как вы могли бы позаботиться), не выглядя похожим на один. Какая у вас проблема, которую вы на самом деле хотите решить? –
@PeterDuniho Это может быть случай с XY проблемой, если я ошибаюсь, что было бы хорошо знать. Я отредактирую, чтобы включить более подробную информацию в ближайшее время. – EJoshuaS
@PeterDuniho Я отредактировал - это проясняет это? – EJoshuaS