Qual é a melhor forma de saber se um método é uma propriedade de dentro da Política de Injeção?
-
09-06-2019 - |
Pergunta
Eu tenho um processador personalizado aplicado a uma classe (usando a Diretiva de Injeção de Aplicação Bloco de entlib 4) e eu gostaria de saber se o método de entrada é de propriedade quando Chamar é chamado.É o que meu processador parece.
[ConfigurationElementType(typeof(MyCustomHandlerData))]
public class MyCustomHandler : ICallHandler
{
public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext)
{
if (input.MethodBase.IsPublic && (input.MethodBase.Name.Contains("get_") || input.MethodBase.Name.Contains("set_")))
{
Console.WriteLine("MyCustomHandler Invoke called with input of {0}", input.MethodBase.Name);
}
return getNext().Invoke(input, getNext);
}
public int Order { get; set; }
}
Como você pode ver com o meu código de exemplo, a melhor maneira que eu pensei até agora é por analisar o nome do método.Não existe uma maneira melhor de fazer isso?
Solução
Você também pode verificar IsSpecialName é verdadeiro.isso vai ser verdade em uma propriedade (entre outras coisas)
Do il nível os métodos são expostos da seguinte maneira (utilizando o Ambiente.ExitCode como exemplo):
.method public hidebysig specialname static int32 get_ExitCode() cil managed
.method public hidebysig specialname static void set_ExitCode(int32 'value') cil managed
Se você quiser começar a fantasia você poderia verificar depois de extrair o nome que disse propriedade existe, mas para ser honesto
if (m.IsSpecialName && (m.Attributes & MethodAttributes.HideBySig) != 0))
bem como inicia-se com get_ ou set_, em seguida, você deve ser bom mesmo para as pessoas que utilizam desagradável nomes (falsificando o hidebysig é bastante fácil, fingir que o IsSpecialName seria muito complicado)
Nada é garantido embora.Alguém poderia emitir uma classe com um set_Foo método que parecia apenas um real definir o método, mas, na verdade, não era um conjunto em uma propriedade somente leitura.A menos que você verifique se a propriedade CanRead/CanWrite bem.
Isso me parece loucura para você que você não está esperando deliberada evasão.Um simples utilitário/extensão do método de MethodInfo que fez esta lógica não seria muito difícil e incluindo IsSpecialName quase que certamente iria cobrir todas as suas necessidades.
Outras dicas
Você pode verificar o IsSpecialName propriedade;ele vai ser true para a propriedade getters e setters.No entanto, também será verdade para outros métodos especiais, como operador de sobrecargas.
Eu não estou familiarizado com esse aplicativo bloco, mas, supondo que MethodBase propriedade é do tipo de Sistema.Reflexão.MethodBase, você poderia dar uma olhada no IsSpecialName propriedade.
Um casal de você mencionou usando o "IsSpecialName" propriedade do MethodBase tipo.Enquanto é verdade que o irá retornar true para a propriedade de "receber" ou "conjuntos", que também irá retornar true para sobrecargas de operador, tais como add_EventName ou remove_EventName.Portanto, será necessário examinar outros atributos do MethodBase instância para determinar se o seu assessor de propriedade.Infelizmente, se tudo que você tem é uma referência a um MethodBase instância (o que eu acredito é o caso de interceptação de comportamentos na Unidade framework), não existe real de maneira "limpa" para determinar se um setter de propriedade ou getter.A melhor forma que encontrei é da seguinte maneira:
C#:
bool IsPropertySetter(MethodBase methodBase){
return methodBase.IsSpecialName && methodBase.Name.StartsWith("set_");
}
bool IsPropertyGetter(MethodBase methodBase){
return methodBase.IsSpecialName && methodBase.Name.StartsWith("get_");
}
VB:
Private Function IsPropertySetter(methodBase As MethodBase) As Boolean
Return methodBase.IsSpecialName AndAlso methodBase.Name.StartsWith("set_")
End Function
Private Function IsPropertyGetter(methodBase As MethodBase) As Boolean
Return methodBase.IsSpecialName AndAlso methodBase.Name.StartsWith("get_")
End Function
É um pouco tarde, mas outras pessoas irão ler este também.Além IsSpecialName e verificar o set_ prefixo (operadores op_, evento subscr./remov.tem add_,remove_) você pode verificar se o método é um jogo para qualquer uma das propriedades de métodos como este:
bool isProperty = method.ReflectedType.GetProperties().FirstOrDefault(p =>
p.GetGetMethod().GetHashCode() == method.GetHashCode()
|| p.GetSetMethod().GetHashCode() == method.GetHashCode())!=null;