SkyterX
SkyterX

Reputation: 123

Check if PropertyInfo is interface implementation

What is the correct way to check that a given property info is an implementation of a property from an interface?

There is a class InterfaceMap that solve this problem for methods. But for properties, it provides two separate mappings for getter and setter and there still remains a problem to match those with the corresponding interface methods.

public interface IA
{
    int X { get; set; }
}

public interface IB
{
    int X { get; set; }
}

public class C : IA, IB
{
    public int X { get; set; }
    int IB.X { get; set; }
}

public PropertyInfo GetProperty<TClass, TProperty>(Expression<Func<TClass, TProperty>> getProperty)
{
    return (PropertyInfo)((MemberExpression)getProperty.Body).Member;
}

[Test]
public void Check()
{
    var aProperty = GetProperty((IA x) => x.X);
    var bProperty = GetProperty((IB x) => x.X);
    var cPropertyA = GetProperty((C x) => x.X);
    var cPropertyB = GetProperty((C x) => ((IB)x).X);

    CompareProperties(cPropertyA, aProperty); // True
    CompareProperties(cPropertyA, bProperty); // False
    CompareProperties(cPropertyB, aProperty); // False
    CompareProperties(cPropertyB, bProperty); // True
}

private bool CompareProperties(PropertyInfo classProperty, PropertyInfo interfaceProperty)
{
    // TODO implement 
}

Upvotes: 2

Views: 1135

Answers (1)

O. R. Mapper
O. R. Mapper

Reputation: 20770

From a given PropertyInfo, you can use the GetMethod and SetMethod properties to access the MethodInfo of the getter and setter, respectively.

Thus, it should be possible to compare those in a little helper method:

private static bool MethodsImplements(InterfaceMap interfaceMap,
    MethodInfo interfaceMethod, MethodInfo classMethod)
{
    var implIndex = Array.IndexOf(interfaceMap.InterfaceMethods, interfaceMethod);
    return interfaceMethod == interfaceMap.TargetMethods[implIndex];
}

This can then be used as follows to fulfil your desired method:

var interfaceType = interfaceProperty.DeclaringType;
var interfaceMap = classProperty.DeclaringType.GetInterfaceMap(interfaceType);

var gettersMatch = classProperty.CanRead && interfaceProperty.CanRead
    && MethodImplements(interfaceMap, interfaceProperty.GetMethod, classProperty.GetMethod);

var settersMatch = classProperty.CanWrite && interfaceProperty.CanWrite
    && MethodImplements(interfaceMap, interfaceProperty.SetMethod, classProperty.SetMethod);

Then, return gettersMatch || settersMatch, as the interface property may have only a getter or only a setter.

Upvotes: 1

Related Questions