Я видел нечто подобное раньше.Единственная разница между сгенерированным компилятором и ручным выражением заключается в свойстве ReflectedType
PropertyInfo
- в сгенерированном компилятором коде оно совпадает с DeclaringType
, который в данном случае является базовым классом, тогда как в PropertyInfo
, полученном с помощьюtype.GetProperty
это производный тип, используемый для его получения.
По какой-то неизвестной причине (возможно, ошибка) это сбивает с толку EF Core.Временное решение: изменить код следующим образом:
var property = type.GetProperty(orderByProperty);
if (property.DeclaringType != property.ReflectedType)
property = property.DeclaringType.GetProperty(property.Name);
или использовать вспомогательный метод, подобный этому
static PropertyInfo GetProperty(Type type, string name)
{
for (; type != null; type = type.BaseType)
{
var property = type.GetProperty(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly);
if (property != null) return property;
}
return null;
}
Для поддержки вложенных свойств я бы добавил следующеепомощники
static Expression Property(Expression target, string name) =>
name.Split('.').Aggregate(target, SimpleProperty);
static Expression SimpleProperty(Expression target, string name) =>
Expression.MakeMemberAccess(target, GetProperty(target.Type, name));
, а затем используйте
var propertyAccess = Property(param, orderByProperty);
и
new Type[] { type, orderByExpression.ReturnType },
внутри рассматриваемого метода.