2016-07-14 40 views
2
public class Sample 
{ 
public int Id { get; set; } 
public string Description { get; set; } 
public DateTime EffectiveDate { get; set; } 
} 

IEnumberable<Sample> sampleList; 
//Populate the list 
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)都作爲字符串傳遞。C#Linq篩選器IEnumerable動態屬性和值

我試過如下:

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作爲 「說明」,但拋出的字符串和INT之間incomptable '=' 操作當「Id」作爲filterColumn傳遞並出現一些filterValue(如「1」)時出錯。

感謝任何幫助。謝謝

+0

您的第一個人正在檢查它,*屬性名稱*與指定的屬性值相同。您需要在PropertyInfo上調用'.GetValue(x,null)'...然後你想使用'Equals'而不是'=='。 –

+0

你爲什麼要做'.AsQueryable()'? – Enigmativity

回答

1

你的第一種方法可以工作。擴展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"); 

這個例子是不是真的安全,因爲沒有類型檢查,以確保該屬性值將要傳遞的數據類型相同。例如,沒有什麼從通過阻止你「說明「和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類使用與您的使用相匹配的過濾器字符串。通常,必須根據數據類型以不同的方式構造過濾器字符串。例如,一個字符串需要引號(你有),但整數值不使用引號。

1

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

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)); 
} 

這裏的優點是,可以執行更復雜的比較,例如,通過值的範圍,或那些含有一個以上的屬性添加自定義過濾器。