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