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”属性,有时是“描述”属性来过滤列表。只想将属性名称(filterColumn)和属性值(filterValue)作为字符串传递。
我尝试了以下内容:
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”时,会在string和int错误之间抛出不可编译的'='运算符。
感谢任何帮助。感谢
答案 0 :(得分:2)
您的第一种方法可行。扩展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");
这个例子不是很安全,因为没有类型检查来确保属性值与你传入的数据类型相同。例如,没有什么能阻止你传递&#34;描述&# 34;和100作为参数。您无法在整数和字符串之间进行有意义的比较,因此您总是会得到一个空结果。 Equals方法不会抛出异常,只是看到两个对象不同。正如Jon指出的那样,在这种情况下,你总是希望使用Equals而不是&#34; ==&#34;运营商。 Equals方法用于比较内容,而#34; ==&#34;比较参考。例如:
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)
另外,请注意,在使用&#34; ==&#34;时,字符串会有一些特殊的行为。运营商。要记住的重要一点是引用(容器)和内容之间存在差异。您想要比较内容,这意味着等于。 (我注意到Visual Studio中的立即窗口在使用&#34; ==&#34;时对字符串的结果不一致。我怀疑这是因为字符串引用可以但不总是在该窗口中进行优化。)
您声明您的第二种方法有效。我没有在标准的IEnumerable.Where方法中看到过这种类型的过滤字符串。所以我猜你正在使用一些扩展。您的示例无法正常显示。 DataTable类使用与您的用法匹配的筛选字符串。通常,必须基于数据类型以不同方式构造过滤器字符串。例如,字符串需要引号(您有)但整数值不使用引号。
答案 1 :(得分: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));
}
此处的优点是您可以执行更复杂的比较,例如按值范围添加自定义过滤器,或者包含多个属性的过滤器。