Como determino qual interface é referenciada por um objeto Methodinfo explicitamente implementado?
-
21-09-2019 - |
Pergunta
eu tenho um MethodInfo
Objeto que representa um método de interface explicitamente implementado, como segue.
MethodInfo GetMethod()
{
return typeof(List<>).GetMethod(
"System.Collections.IEnumerable.GetEnumerator",
BindingFlags.Instance | BindingFlags.NonPublic);
}
Como faço para consultar isso MethodInfo
objetar para obter o tipo de interface que ele implementa, um Type
objeto representando System.Collections.IEnumerable
? o InterfaceMapping
estrutura fornece a operação inversa, obtendo o MethodInfo
Objeto de um tipo que implementa uma determinada interface, para que não funcione.
Observe que este é um exemplo artificial, pois posso analisar claramente o nome do método para essas informações. Eu gostaria de evitar fazer isso, se possível.
Solução
Não sei de uma maneira direta de fazer isso, mas você obviamente pode usar o interfaceMapping ao contrário: iterar em todas as interfaces implementadas pelo tipo de declaração do método, verificando se o método estiver no mapa da interface para essa interface:
foreach (Type itf in method.DeclaringType.GetInterfaces())
{
if (method.DeclaringType.GetInterfaceMap(itf).TargetMethods.Any(m => m == method))
{
Console.WriteLine("match: " + itf.Name);
}
}
Embora isso possa parecer um pouco ineficiente, a maioria dos tipos implementa poucas interfaces suficientes para que não deve ser um grande negócio. Agradeço que não é terrivelmente elegante!
Outras dicas
Desculpe pela minha primeira resposta, no começo, tentei chegar ao método através do InterfaceMap
estrutura e os métodos em este estrutura na verdade Faz relatar a interface como o DeclaringType
. Então eu me puxa com ele e não percebi que estava sutilmente quebrado usando o método que você postou para obter o MethodInfo
.
A vantagem, porém, é que essa diferença sutil levou à percepção de que o MethodInfo
para o método da interface e o MethodInfo
Para o método de implementação, não são realmente o mesmo método. E, ao pensar mais, tenho certeza de que o que você quer fazer é impossível de fazer de maneira confiável.
As implementações explícitas de interface em C# são um pouco de açúcar sintático sobre a maneira como ele realmente funciona no CLR. Em outros idiomas, um único método de concreto pode implementar vários métodos de interface da mesma maneira que uma classe de concreto pode implementar vários tipos de interface. Por exemplo, no vb.net, é perfeitamente legal fazer isso:
Public Overrides Function Baz() As String Implements IFoo.Foo, IBar.Bar
Aqui você tem um método que está implementando explicitamente dois métodos de interface. Se fosse possível obter a classe de interface original - ou mesmo o método de interface original - qual você receberia? Como você resolve a ambiguidade?
Não sou especialista nos internos do CLR, mas acredito que os mapas de interface são unidirecionais. Quando você implementa uma interface ou método, implicitamente ou explicitamente, o compilador cria um mapa a partir de a interface para A implementação, e isso é tudo o que precisa para lidar com chamadas de método em relação à interface.
Pense nos nomes de métodos gerados por C#como quase coincidentes. Mesmo que o nome do método seja System.Collections.IEnumerable.GetEnumerator
, isso realmente é apenas um nome, e na verdade não há nenhuma informação sobre System.Collections.IEnumerable
codificado no próprio método.
Tentar MethodInfo.DeclaringType
.