簡體   English   中英

C#Linq篩選器IEnumerable動態屬性和值

[英]C# Linq Filter IEnumerable dynamic property and value

public class Sample
{
public int Id { get; set; }
public string Description { get; set; }
public DateTime EffectiveDate { get; set; }
}

IEnumberable<Sample> sampleList;
//Populate the list

現在,我想通過“ Id”屬性有時甚至“ Description”屬性來過濾列表。 只想將屬性名稱(filterColumn)和屬性值(filterValue)都傳遞為string。

我嘗試了以下方法:

IEnumerable<Sample> result = sampleList.Where(x => x.GetType().GetProperty(filterColumn).Name == filterValue);

string whereQuery = string.Format(" {0} = \"{1}\"", filterColumn, filterValue);
IEnumerable<Sample> result = sampleList.AsQueryable().Where(whereQuery);

第二個選項有效,如果我將filterColumn傳遞為“ Description”,但是當將“ Id”作為filterColumn和一些filterValue(如“ 1”)傳遞時,在字符串和int錯誤之間拋出了不可兼容的'='運算符。

感謝任何幫助。 謝謝

您的第一種方法可行。 擴展Jon Skeet的評論,以下是調整后的聲明。

IEnumerable<Sample> result = sampleList.Where(
  x => x.GetType().GetProperty(filterColumn).GetValue(x, null).Equals(filterValue)
);

要對此進行一些介紹,您必須允許使用不同的數據類型。 您可以通過至少兩種方式執行此操作:使用通用方法或使用對象數據類型。 出於說明目的,我將使用對象方法。

public IEnumerable<Sample> GetFiltered(
  IEnumerable<Sample> samples, string filtercolumn, object filtervalue
{ 
   return samples.Where(
      x => x.GetType().GetProperty(filtercolumn).GetValue(x, null).Equals(filtervalue)
   );
}

IEnumberable<Sample> sampleList;

var byId = GetFiltered(sampleList, "Id", 100);
var byDescription = GetFiltered(sampleList, "Description", "Some Value");

此示例並不十分安全,因為沒有類型檢查來確保屬性值將與您傳入的數據類型相同。例如,沒有什么阻止您傳遞“ Description”和100作為參數。 您無法在整數和字符串之間進行有意義的比較,因此您總是會得出空的結果。 Equals方法不會引發異常,它只是看到兩個對象是不同的。 正如Jon所指出的,在這種情況下,您總是要使用Equals而不是“ ==”運算符。 Equals方法用於比較內容,而“ ==“用於比較引用。 例:

Console.WriteLine(12 == 12); 
// True

object a = 12;
object b = 12;

Console.WriteLine(a == b); 
// False - because, due to boxing, a and b are separate objects
// that happen to contain the same value. (Check out "boxing" 
// if this doesn't make sense.)

Console.WriteLine(a.Equals(b)); 
// True - because the Equals method compares content (value)

另外,請注意,使用“ ==”運算符時,字符串具有某些特殊行為。 要記住的重要一點是,引用(容器)和內容之間存在差異。 您要比較內容,這意味着等於。 (我已經注意到,在使用“ ==”時,Visual Studio中的即時窗口與字符串有關的結果不一致。我懷疑這是因為可以在該窗口中(但並非總是)優化字符串引用。)

您聲明第二種方法可行。 我沒有在標准IEnumerable.Where方法中看到這種類型的過濾器字符串。 所以我猜您正在使用一些擴展。 您的示例不起作用,如圖所示。 DataTable類使用與您的用法匹配的過濾器字符串。 通常,必須根據數據類型以不同的方式構造過濾器字符串。 例如,字符串需要用引號引起來,而整數值不使用引號。

您擁有的另一個選擇是使用所需的操作來設置字典。

public IEnumerable<Sample> GetFiltered(
    IEnumerable<Sample> samples, string property, string value)
{
    var map = new Dictionary<string, Func<string, Func<Sample, bool>>>()
    {
        { "Description", v => s => s.Description == v },
        { "Id", v => s => s.Id == int.Parse(v) },
    };
    return samples.Where(map[property](value));
}

這樣做的好處是您可以執行更復雜的比較,例如按值范圍或包含多個屬性的值范圍添加自定義過濾器。

暫無
暫無

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

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