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.

Foi útil?

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.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top