[英]How to use expressions to sort a collection based on an inherited interface property
This problem has been discussed to an extent in this question: Create Generic Expression from string property name but perhaps I'm missing the answer, or it is subtly different. 在以下问题中已在某种程度上讨论了此问题: 从字符串属性名称创建通用表达式,但可能我错过了答案,或者它有所不同。
I have the following queryable extension method: 我有以下可查询的扩展方法:
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);
}
For the purposes of this problem let us assume that the queryable source instance has a property called 'Created' which is a type of DateTime. 出于此问题的目的,我们假设可查询源实例具有一个名为“ Created”的属性,该属性是DateTime的一种类型。 If we define a class that has the property 'Created' on it and then OrderByDescending then the above will work fine.
如果我们定义一个具有“ Created”属性的类,然后定义OrderByDescending,则以上内容将可以正常工作。 eg
例如
var queryable = new List<EntityClassWithCreatedProperty>().AsQueryable();
var result = queryable.OrderByPropertyDescending("Created").ToList();
If we do the same thing but with an interface such as ICreated which has the Created property on it: 如果我们做同样的事情,但是具有ICreated之类的接口,该接口上具有Created属性:
public interface ICreated
{
DateTime Created { get; }
}
Then the following also works: 然后,以下内容也适用:
var queryable = new List<ICreated>().AsQueryable();
var result = queryable.OrderByPropertyDescending("Created").ToList();
If however, you have the following interface hierarchy: 但是,如果您具有以下接口层次结构:
public interface ITimestamped : ICreated
{
...
}
Then the following will fail: 然后,以下操作将失败:
var queryable = new List<ITimestamped>().AsQueryable();
var result = queryable.OrderByPropertyDescending("Created").ToList();
With the similar error message to that of the other question: Instance property 'Created' is not defined for type ITimestamped. 出现与另一个问题类似的错误消息:未为ITimestamped类型定义实例属性'Created'。 I'm assuming that I need to find the property on the declaring type of interface (which I can do by crawling the source type) but then what do I do with it?
我假设我需要在声明的接口类型上找到属性(可以通过爬网源类型来完成此操作),但是该怎么办呢? Most attempts I have tried result in the incorrect original source type not being cast-able back to the IQueryable.
我尝试过的大多数尝试都会导致错误的原始源类型无法强制转换回IQueryable。 Do I need to use a ConvertType call somewhere?
我需要在某个地方使用ConvertType调用吗? Thanks.
谢谢。
I would use the other Expression.Property() method that takes a propertyInfo, eg 我将使用另一个采用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);
}
At this point your question has nothing to do with expressions, it's a simple reflection question, and you have to find the correct way to get the properties you want. 此时,您的问题与表达式无关,这是一个简单的反射问题,您必须找到获取所需属性的正确方法。 There are a lot of scenarios here.
这里有很多场景。 For your exact one, meaning get property from parent interface, you can do something like:
对于您的确切含义(即从父界面获取属性),您可以执行以下操作:
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;
}
DISCLAIMER! 免责声明! This is by no means the best way to get a property from a type, but it should work in your case.
这绝不是从类型中获取属性的最佳方法,但它应适用于您的情况。 You should google around to find an implementation for FindMyProperty that satisfies all your requirements :)
您应该四处搜寻以找到满足您所有要求的FindMyProperty实现:)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.