我正在尝试使用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();
}
答案 0 :(得分:1)
a。反射(如果propertyName的值与实际属性名称匹配)
var t = typeof(...your type...);
var pi = t.GetProperty(propertyName);
CurrentFilterList = AfterFilterList
.Where(x => pi.GetValue(x).ToString() == propertyValue)
.ToList();
b。如果属性名称不匹配,则可以尝试以下方法:
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
也可以使用反射来动态构建-只需遍历所有道具并动态创建函数/表达式。
答案 1 :(得分:0)
这是一个无需反射即可创建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;
}
但是,这又仅仅是一个例子。对于您所描述的场景来说,这太过分了。