这个问题已经在这个问题中得到了一定程度的讨论:Create Generic Expression from string property name但也许我错过了答案,或者它有些微妙的不同。
我有以下可查询的扩展方法:
public static IQueryable<TSource> OrderByPropertyDescending<TSource>(IQueryable<TSource> source, string propertyName)
{
var sourceType = typeof (TSource);
var parameter = Expression.Parameter(sourceType, "item");
var orderByProperty = Expression.Property(parameter, propertyName);
var orderBy = Expression.Lambda(orderByProperty, new[] { parameter });
return Queryable.OrderByDescending(source, (dynamic) orderBy);
}
出于这个问题的目的,让我们假设可查询源实例有一个名为&#39; Created&#39;这是一种DateTime。如果我们定义一个具有“创建”属性的类。在它上面然后OrderByDescending然后上面的工作正常。 e.g。
var queryable = new List<EntityClassWithCreatedProperty>().AsQueryable();
var result = queryable.OrderByPropertyDescending("Created").ToList();
如果我们做同样的事情,但使用ICreated等具有Created属性的界面:
public interface ICreated
{
DateTime Created { get; }
}
然后以下内容也有效:
var queryable = new List<ICreated>().AsQueryable();
var result = queryable.OrderByPropertyDescending("Created").ToList();
但是,如果您具有以下界面层次结构:
public interface ITimestamped : ICreated
{
...
}
然后以下将失败:
var queryable = new List<ITimestamped>().AsQueryable();
var result = queryable.OrderByPropertyDescending("Created").ToList();
使用与其他问题类似的错误消息:Instance property&#39; Created&#39;没有为ITimestamped类型定义。我假设我需要在声明类型的接口上找到属性(我可以通过爬行源类型来完成)但是我该怎么做呢?我尝试过的大多数尝试都会导致不正确的原始源类型无法转换回IQueryable。我是否需要在某处使用ConvertType调用?感谢。
答案 0 :(得分:1)
我会使用另一个带有propertyInfo的Expression.Property()方法,例如
public static IQueryable<TSource> OrderByPropertyDescending<TSource>(IQueryable<TSource> source, string propertyName)
{
var sourceType = typeof (TSource);
var parameter = Expression.Parameter(sourceType, "item");
var propertyInfo = FindMyProperty(sourceType, propertyName);
var orderByProperty = Expression.Property(parameter, propertyInfo);
var orderBy = Expression.Lambda(orderByProperty, new[] { parameter });
return Queryable.OrderByDescending(source, (dynamic) orderBy);
}
private static PropertyInfo FindMyProperty(Type type, string propertyName)
{
return type.GetProperty(propertyName);
}
此时你的问题与表达无关,这是一个简单的反思问题,你必须找到获得所需属性的正确方法。这里有很多场景。对于您的确切一个,意味着从父接口获取属性,您可以执行以下操作:
private static PropertyInfo FindMyProperty(Type type, string propertyName)
{
var result = type.GetProperty(propertyName);
if (result == null)
{
foreach(var iface in type.GetInterfaces())
{
var ifaceProp = FindMyProperty(iface, propertyName);
if (ifaceProp != null)
return ifaceProp;
}
}
return result;
}
声明! 这绝不是从类型中获取属性的最佳方法,但它应该适用于您的情况。你应该谷歌找到满足你所有要求的FindMyProperty实现:)