Возможно, вам понадобится InterfaceMapping . Вы можете получить это из фактического типа, вызвав GetInterfaceMap(typeof(interface))
, т.е.
InterfaceMapping mapping = typeof(Employee).GetInterfaceMap(typeof(IEmployee));
Теперь отображение будет содержать поля InterfaceMethods
, которые будут содержать методы, которые вы видите при отражении интерфейса, и TargetMethods
, которые являются методами реализации класса. Обратите внимание, что это отображает методы получения из интерфейса на методы получения из целевого класса. Вам нужно будет найти правильное свойство интерфейса, сопоставив метод получения различных свойств класса с найденным методом получения.
Type interfaceType = typeof(IEmployee);
Type classType = typeof(Employee);
PropertyInfo nameProperty = interfaceType.GetProperty("Name");
MethodInfo nameGetter = nameProperty.GetGetMethod();
InterfaceMapping mapping = classType.GetInterfaceMap(interfaceType);
MethodInfo targetMethod = null;
for (int i = 0; i < mapping.InterfaceMethods.Length; i++)
{
if (mapping.InterfaceMethods[i] == nameGetter)
{
targetMethod = mapping.TargetMethods[i];
break;
}
}
PropertyInfo targetProperty = null;
foreach (PropertyInfo property in classType.GetProperties(
BindingFlags.Instance | BindingFlags.GetProperty |
BindingFlags.Public | BindingFlags.NonPublic)) // include non-public!
{
if (targetMethod == property.GetGetMethod(true)) // include non-public!
{
targetProperty = property;
break;
}
}
// targetProperty is the actual property
Внимание: Обратите внимание на использование BindingFlags.NonPublic
и GetGetMethod(true)
здесь для доступа к закрытым членам. Если у вас есть явная реализация интерфейса, на самом деле нет открытого свойства, соответствующего свойству интерфейса, вместо этого есть частное свойство с именем Some.NameSpace.IEmployee.Name
, которое отображается (что, конечно, является вашей явной реализацией).
Когда вы нашли нужную недвижимость, вы можете просто позвонить
ParameterExpression p = Expression.Parameter("e", typeof(T));
Expression<Func<T, U>> lambda = Expression.Lambda<Func<T, U>>(
Expression.Property(p, targetProperty), p);
и вы получите лямбда-выражение, которое использует свойства класса, а не свойства интерфейса.