[英]How to use expressions to sort a collection based on an inherited interface property
在以下問題中已在某種程度上討論了此問題: 從字符串屬性名稱創建通用表達式,但可能我錯過了答案,或者它有所不同。
我有以下可查詢的擴展方法:
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);
}
出於此問題的目的,我們假設可查詢源實例具有一個名為“ Created”的屬性,該屬性是DateTime的一種類型。 如果我們定義一個具有“ Created”屬性的類,然后定義OrderByDescending,則以上內容將可以正常工作。 例如
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();
出現與另一個問題類似的錯誤消息:未為ITimestamped類型定義實例屬性'Created'。 我假設我需要在聲明的接口類型上找到屬性(可以通過爬網源類型來完成此操作),但是該怎么辦呢? 我嘗試過的大多數嘗試都會導致錯誤的原始源類型無法強制轉換回IQueryable。 我需要在某個地方使用ConvertType調用嗎? 謝謝。
我將使用另一個采用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實現:)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.