簡體   English   中英

如何使用表達式基於繼承的接口屬性對集合進行排序

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM