Brincando Com LINQ: Obtendo As Implementações De Propriedades De Interfaces
Hoje, o meu amigo Nuno estava a escrever algum código para obter as PropertyInfos da implementação de uma interface por parte de classe.
Dada este interface:
public interface ISomeInterface
{
int IntProperty { get; set; }
string StringProperty { get; }
void Method();
}
e esta classe:
public class SomeClass : ISomeInterface
{
int ISomeInterface.IntProperty { get; set; }
public int IntProperty { get; private set; }
public string StringProperty { get; private set; }
public void Method() { }
}
o Nuno queria obter:
- Int32 ISomeInterface.IntProperty
- System.String StringProperty
O código é relativamente simples. Primeiro é necessário obter os mapeamentos da interface:
typeof(SomeClass).GetInterfaceMap(typeof(ISomeInterface)).TargetMethods
e filtrar por PropertyInfos para as quais o MethodInfo é parte da sua implementação (implementa o método get ou o método set).
Algo como isto:
public static bool Implements(this MethodInfo methodInfo, PropertyInfo propertyInfo)
{
return (propertyInfo.GetGetMethod(true) == methodInfo) || (propertyInfo.GetSetMethod(true) == methodInfo);
}
Mas o que me chamou a atenção foi que, com os métodos de extensão acima, posso usar LINQ para obter as desejadas PropertyInfos.
Algo assim:
public static IEnumerable<PropertyInfo> GetInterfacePropertyImplementation(Type implementer, Type implemented)
{
return (from propertyInfo in implementer.GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).AsEnumerable()
from methodInfo in implementer.GetInterfaceMap(implemented).TargetMethods.AsEnumerable()
where methodInfo.Implements(propertyInfo)
select propertyInfo).Distinct();
}
Para a classe e interface do exemplo, usar o método acimo seria algo como:
var q = GetInterfacePropertyImplementation(typeof(SomeClass), typeof(ISomeInterface));
foreach (var p in q)
{
Console.WriteLine(p);
}
O que produzirá o seguinte resultado:
Int32 ISomeInterface.IntProperty
System.String StringProperty
ACTUALIZADO: A implementação anterior era demasiado complexa e baseada em strings. Obrigado, Nuno.