我使用IQueryable<Person>
类的实例在Person
上有一个顺序过滤器,运行方式如下:
public IQueryable<Person> FilterPeopleOnPersonCriteria(IQueryable<Person> people, Person p)
{
if (!string.IsNullOrEmpty(p.FirstName))
{
people = people.Where(x => x.FirstName == p.FirstName);
}
if (!string.IsNullOrEmpty(p.Surname))
{
people = people.Where(x => x.Surname == p.Surname);
}
// etc. for all Person's string properties
return people;
}
我想如果可以通过people
,Person
和我想申请的property
,就可以烘干自己并替换if / else的重复项过滤器转换为特定的过滤器方法,如下所示:
public IQueryable<Person> FilterPeopleOnProperty(IQueryable<Person> people, Person p, Person.Property personProperty)
{
if (!string.IsNullOrEmpty(p.personProperty))
{
people = people.Where(x => x.personProperty == p.personProperty);
}
return people;
}
最后,我的原始查询如下:
public IQueryable<Person> FilterPeopleOnPersonCriteria(IQueryable<Person> people, Person p)
{
people = FilterPeopleOnPersonProperty(people, p, new Person().FirstName);
people = FilterPeopleOnPersonProperty(people, p, new Person().Surname);
// etc. for all properties on p
return people;
}
我假设使用某些通用类型和我的Person
类的新实例是可能的,但不知道从哪里开始。
答案 0 :(得分:1)
我想这就是您要寻找的东西
namespace Extensions
{
using System;
using System.Linq;
using System.Collections.Generic;
public static class IEnumerableExtensions
{
public static IEnumerable<T> WhereIf<T>(this IEnumerable<T> collection, bool condition, Func<T, bool> predicate)
{
return condition ? collection.Where(predicate) : collection;
}
}
}
仅当条件为真时,我们才进行过滤。我使用IEnumerable<T>
是因为它更通用,并且还是由IQueryable<T>
实现的,但是您仍然可以使用IQueryable<T>
来代替。如果您想使用IQueryable<T>
,则需要使用System.Linq.Expressions
,并用Func<T, bool>
替换Expression<Func<T, bool>>
。
与您的用例类似的用例如下:
public IEnumerable<Person> FilterPeople(IEnumerable<Person> people, Person person)
{
return people.WhereIf(!string.IsNullOrEmpty(person.FullName), p => p.FullName == person.FullName);
}
答案 1 :(得分:1)
如果我理解您的要求是正确的,那么您想传递一个Person对象,其中填充了一些(字符串)属性,例如“ Starts *”,“ * ends”,“ ExactValue”,并且您将该Person用作QBE(按示例查询。即:
Person p = new Person {FirstName="S*", LastName="*doe", Country="USA"};
将进行以下搜索:
people.Where(p => p.FirstName.StartsWith("S") &&
p.LastName.EndsWith("doe") &&
p.Country == "USA");
对吗?如果是这样,那么我认为您可以利用Scott Gu's dynamic Linq,一些好人可以在NuGet和documented here上找到他们。
以下是使用该Nuget库(System.Linq.Dynamic)的一些示例代码:
public IQueryable<Person> FilterPeopleOnPersonCriteria(IQueryable<Person> people, Person p)
{
var t = p.GetType();
var fields = t
.GetFields()
.Where(x => x.FieldType == typeof(string) &&
!string.IsNullOrEmpty((string)t.GetField(x.Name).GetValue(p)))
.Select(x => x.Name);
foreach (var f in fields)
{
var fi = t.GetField(f);
string pVal = (string)fi.GetValue(p);
if (pVal.Contains('*'))
{
var query = $"{f}.{(pVal.StartsWith("*") ? "Ends" : "Starts")}With(@0)";
people = people.Where(query, pVal.Replace("*", ""));
}
else
{
var query = $"{f} == @0";
people = people.Where(query, pVal);
}
}
return people;
}
您会这样称呼它:
var personQBE = new Person {
FirstName="J*",
LastName="Doe"
});
var result = FilterPeopleOnPersonCriteria(people, personQBE);