Reputation: 123
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
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