Ao efetuar logon em C #, como posso aprender o nome do método que chamou o método atual? Eu sei tudo sobre System.Reflection.MethodBase.GetCurrentMethod()
, mas quero dar um passo abaixo disso no rastreamento de pilha. Eu considerei analisar o rastreamento da pilha, mas espero encontrar uma maneira mais explícita e limpa, algo como Assembly.GetCallingAssembly()
mas para métodos.
c#
.net
logging
stack-trace
system.diagnostics
duvidoso
fonte
fonte
StackTrace
,StackFrame
eCallerMemberName
) e postou os resultados como uma essência para que outros vejam aqui: gist.github.com/wilson0x4d/7b30c3913e74adf4ad99b09163a57a1fRespostas:
Tente o seguinte:
uma linha:
É do método Get Calling usando Reflection [C #] .
fonte
No C # 5, você pode obter essas informações usando as informações do chamador :
Você também pode obter o
[CallerFilePath]
e[CallerLineNumber]
.fonte
[CallerTypeName]
foi retirado do quadro actual .Net (4.6.2) e Core CLRVocê pode usar as informações do chamador e os parâmetros opcionais:
Este teste ilustra isso:
Enquanto o StackTrace trabalha muito rápido acima e não seria um problema de desempenho na maioria dos casos, as informações do chamador ainda são muito mais rápidas. Em uma amostra de 1000 iterações, registrei o clock 40 vezes mais rápido.
fonte
CachingHelpers.WhoseThere("wrong name!");
==>"wrong name!"
porque oCallerMemberName
é apenas substitui o valor padrão.this
parâmetro explícito para um método de extensão. Além disso, Olivier está correto, você pode passar um valor e[CallerMemberName]
não é aplicado; em vez disso, funciona como uma substituição onde o valor padrão normalmente seria usado. De fato, se olharmos para a IL, podemos ver que o método resultante não é diferente do que normalmente seria emitido para um[opt]
arg, a injeção deCallerMemberName
é, portanto, um comportamento CLR. Por fim, os documentos: "Os atributos [...] de informações do chamador afetam o valor padrão que é passado quando o argumento é omitido "async
amigável, o queStackFrame
não o ajudará. Também não afeta ser chamado de um lambda.Uma rápida recapitulação das 2 abordagens, com a comparação de velocidade sendo a parte importante.
http://geekswithblogs.net/BlackRabbitCoder/archive/2013/07/25/c.net-little-wonders-getting-caller-information.aspx
Determinando o chamador em tempo de compilação
Determinando o chamador usando a pilha
Comparação das 2 abordagens
fonte
Podemos melhorar um pouco o código do Sr. Assad (a resposta atual aceita) instanciando apenas o quadro que realmente precisamos em vez da pilha inteira:
Isso pode ter um desempenho um pouco melhor, embora, com toda a probabilidade, ele ainda precise usar a pilha completa para criar esse único quadro. Além disso, ele ainda possui as mesmas ressalvas que Alex Lyman apontou (o otimizador / código nativo pode corromper os resultados). Finalmente, você pode querer verificar para ter certeza de que
new StackFrame(1)
ou.GetFrame(1)
não voltarnull
, por mais improvável que essa possibilidade possa parecer.Veja esta pergunta relacionada: Você pode usar a reflexão para encontrar o nome do método atualmente em execução?
fonte
new ClassName(…)
seja igual a nulo?Em geral, você pode usar a
System.Diagnostics.StackTrace
classe para obter umSystem.Diagnostics.StackFrame
e, em seguida, usar oGetMethod()
método para obter umSystem.Reflection.MethodBase
objeto. No entanto, existem algumas ressalvas nessa abordagem:( NOTA: Estou apenas expandindo a resposta fornecida por Firas Assad .)
fonte
A partir do .NET 4.5, você pode usar os Atributos de Informações do Chamador :
CallerFilePath
- O arquivo de origem que chamou a função;CallerLineNumber
- Linha de código que chamou a função;CallerMemberName
- Membro que chamou a função.Esse recurso também está presente no ".NET Core" e no ".NET Standard".
Referências
CallerFilePathAttribute
ClasseCallerLineNumberAttribute
ClasseCallerMemberNameAttribute
Classefonte
Observe que isso não será confiável no código de liberação, devido à otimização. Além disso, a execução do aplicativo no modo sandbox (compartilhamento de rede) não permitirá que você pegue o quadro da pilha.
Considere a programação orientada a aspectos (AOP), como o PostSharp , que em vez de ser chamado pelo código, modifica o código e, portanto, sabe onde está o tempo todo.
fonte
Obviamente, esta é uma resposta tardia, mas eu tenho uma opção melhor se você pode usar o .NET 4.5 ou mais:
Isso imprimirá a data e hora atuais, seguidas por "Namespace.ClassName.MethodName" e terminando com ": text".
Saída de amostra:
Uso da amostra:
fonte
fonte
Talvez você esteja procurando algo parecido com isto:
fonte
Uma aula fantástica está aqui: http://www.csharp411.com/c-get-calling-method/
fonte
Outra abordagem que usei é adicionar um parâmetro ao método em questão. Por exemplo, em vez de
void Foo()
, usevoid Foo(string context)
. Em seguida, passe uma string exclusiva que indica o contexto de chamada.Se você precisar apenas do chamador / contexto para desenvolvimento, poderá remover o
param
antes do envio.fonte
Para obter o Nome do método e o Nome da classe, tente o seguinte:
fonte
será o suficiente, eu acho.
fonte
Dê uma olhada no nome do método de log no .NET . Cuidado ao usá-lo no código de produção. O StackFrame pode não ser confiável ...
fonte
Também podemos usar lambda's para encontrar o chamador.
Suponha que você tenha um método definido por você:
e você quer encontrar o chamador.
1 . Altere a assinatura do método para que tenhamos um parâmetro do tipo Action (o Func também funcionará):
2 . Nomes Lambda não são gerados aleatoriamente. A regra parece ser:> <CallerMethodName> __X em que CallerMethodName é substituído pela função anterior e X é um índice.
3 . Quando chamamos MethodA, o parâmetro Action / Func deve ser gerado pelo método chamador. Exemplo:
4 . Dentro do MethodA agora podemos chamar a função helper definida acima e encontrar o MethodInfo do método chamador.
Exemplo:
fonte
Informação extra para resposta de Firas Assaad.
Eu usei
new StackFrame(1).GetMethod().Name;
no .net core 2.1 com injeção de dependência e estou recebendo o método de chamada como 'Iniciar'.Eu tentei com
[System.Runtime.CompilerServices.CallerMemberName] string callerName = ""
e isso me dá o método de chamada corretofonte
fonte