簡體   English   中英

如何根據通用屬性過濾列表

[英]How to filter the list based on generic property

我正在嘗試在使用LINQ的同時刪除硬編碼。 基本上,我有10個屬性,並且基於選定的屬性,我想過濾列表。 有人可以幫我刪除這種硬編碼嗎,有沒有一種方法可以基於“ propertyName”字符串值獲取屬性的信息,並在過濾列表時使用該信息。 以下是供參考的代碼。如果我的問題有意義,請告訴我。 先謝謝您的幫助。

if (propertyName == "Property1")
                {
                    FilteredList = CurrentList.Where(x => x.property1== propertyValue.ToString()).ToList();
                }
                else if (propertyName == "Property2")
                {
                    FilteredList = CurrentList.Where(x => x.property2== propertyValue.ToString()).ToList();
                }

一種。 反射(如果propertyName的值與實際屬性名稱匹配)

var t = typeof(...your type...);
var pi = t.GetProperty(propertyName);

CurrentFilterList = AfterFilterList
      .Where(x => pi.GetValue(x).ToString() == propertyValue)
      .ToList();

如果屬性名稱不匹配,則可以嘗試以下操作:

var funcs = new Dictionary<string, Func<your_type, object>> 
{
   {"Company", v => v.Company},
   {"InspectionUnit", v => v.InspectionUnit}
};

var f = funcs[propertyName];
CurrentFilterList = AfterFilterList
   .Where(x => f(x) == propertyValue.ToString()).ToList();

代碼可能不准確,但應該表明想法。 #2應該有更好的性能。

BTW funcs剛剛經歷的所有道具迭代,並即時創建funcs中/表情-可以動態使用反射以及建造。

這是一個無需反射即可創建Where條件的函數。 僅出於說明目的,如果無法識別屬性名稱,它將返回一個始終返回true的條件-換句話說,沒有過濾器。 響應未識別的輸入,異常可能更有意義。

private Func<Thing, bool> GetCondition(string propertyName, string propertyValue)
{
    switch (propertyName)
    {
        case "Company":
            return thing => thing.Company == propertyValue;
        case "InspectionUnit":
            return thing => thing.InspectionUnit == propertyValue;
        default: return thing => true;
    }
}

這是使用反射的版本。 只要我們走這條路線,就無需將屬性限制為string值。 只要實現了Equals ,它就可以是任何東西,這對於字符串和值類型都是正確的。

private Func<Thing, bool> GetCondition<TSourceType, TPropertyType>
    (string propertyName, TPropertyType propertyValue)
{
    var property = typeof(TSourceType).GetProperty(
        propertyName, BindingFlags.Instance | BindingFlags.Public);
    if (property?.PropertyType != typeof(TPropertyType))
        return thing => true; // or throw an exception.
    return thing => property.GetValue(thing).Equals(propertyValue);
}

為了提高性能,將反射的屬性存儲在Dictionary<Type, Dictionary<string, PropertyInfo>>類的存儲中將是有益的,因此對於任何給定的類型和屬性名稱,您都可以查找它,而不必重復反射。

在這兩者之間,如果您只是在考慮少數可能的值並且正在處理已知類型,那么我傾向於使用反射。

現在的用法是

非通用/非反射

var condition = GetCondition(propertyName, propertyValue);
var filtered = unfiltered.Where(condition);

通用/反射

var condition = GetCondition<Thing, string>(propertyName, propertyValue);
var filtered = unfiltered.Where(condition);

當我提到將屬性存儲在字典中時,就像這樣:

private readonly Dictionary<Type, Dictionary<string, PropertyInfo>> _properties = new Dictionary<Type, Dictionary<string, PropertyInfo>>();

private PropertyInfo GetProperty(Type sourceType, string propertyName)
{
    if(!_properties.ContainsKey(sourceType))
        _properties.Add(sourceType, new Dictionary<string, PropertyInfo>());
    if (_properties[sourceType].ContainsKey(propertyName))
        return _properties[sourceType][propertyName];
    var property = sourceType.GetProperty(propertyName, BindingFlags.Instance | BindingFlags.Public);
    _properties[sourceType].Add(propertyName, property);
    return property; // could be null;
}

但是,這僅是一個例子。 對於您所描述的場景而言,這太過分了。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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