Playing With LINQ: Getting Interface Property Implementations
Today, my friend Nuno was writing some code to get the PropertyInfos of a class implementation of an interface.
Given this interface:
public interface ISomeInterface { int IntProperty { get; set; } string StringProperty { get; } void Method(); }
and this class:
public class SomeClass : ISomeInterface { int ISomeInterface.IntProperty { get; set; } public int IntProperty { get; private set; } public string StringProperty { get; private set; } public void Method() { } }
Nuno wanted to retrieve:
- Int32 ISomeInterface.IntProperty
- System.String StringProperty
The code is fairly simple. First we need to get the interface mappings for the class:
typeof(SomeClass).GetInterfaceMap(typeof(ISomeInterface)).TargetMethods
and get all PropertyInfos for which the MethodInfo in the list is part of the implementation of the property (is either the set method or the get method).
Something like his:
public static bool Implements(this MethodInfo methodInfo, PropertyInfo propertyInfo) { return (propertyInfo.GetGetMethod(true) == methodInfo) || (propertyInfo.GetSetMethod(true) == methodInfo); }
But what caught my eye was that, with the above extension methods, I can use LINQ to retrieve a list of the desired PropertyInfos.
Something like this:
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(); }
For the sample class and interface, the usage would be something like this:
var q = GetInterfacePropertyImplementation(typeof(SomeClass), typeof(ISomeInterface));foreach (var p in q) { Console.WriteLine(p); }
Which would produce the following output:
Int32 ISomeInterface.IntProperty System.String StringProperty
UPDATED: The previous implementation was overcomplicated and had some string based logic. Kudos to Nuno.