C# 动态LINQ滤波

C# 动态LINQ滤波,c#,linq,C#,Linq,如何使用不同于模型的字段创建动态搜索列表 public class UserModel { public int UserId { get; set; } public string FirstName { get; set; } public string LastName { get; set; } public string DisplayName { get {return $

如何使用不同于模型的字段创建动态搜索列表

public class UserModel
    {
        public int UserId { get; set; }
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public string DisplayName
        {
            get {return $"{ LastName }, { FirstName }"; }            
        }
     }
// Sample search
private void Search(string fieldname, string searchString)
        {
            List<UserModel> data = Users.Where(x => x.fieldname == searchString).ToList();
        }
公共类用户模型
{
public int UserId{get;set;}
公共字符串名{get;set;}
公共字符串LastName{get;set;}
公共字符串显示名
{
获取{return$“{LastName},{FirstName}”;}
}
}
//样本搜索
私有无效搜索(字符串字段名、字符串搜索字符串)
{
List data=Users.Where(x=>x.fieldname==searchString.ToList();
}

快速而肮脏的方法是使用带有预定义属性名称的
开关。我不建议允许用户指定过滤依据的确切属性或列,因为这会带来隐私风险和安全漏洞(例如,允许用户通过电子邮件、姓名或密码搜索其他用户,而您没有意识到这一点)

这些扩展方法可以这样使用:

private async Task<List<UserModel>> SearchUsersAsync( UserProperty filterProp = UserProperty.None, String filterValue = null, UserProperty sortProp = UserProperty.None, Boolean sortAscending = true )
{
    List<User> users = await this.Users
        .WhereProperty( filterProp, filterValue )
        .OrderByProperty( sortProp, sortAscending )
        .ToListAsync()
        .ConfigureAwait(false);

    List<UserModel> userViewModels = users
        .Select( u => UserModel.FromUserEntity( u ) )
        .ToList();

    return userViewModels;
}
private async任务SearchUsersAsync(UserProperty filterProp=UserProperty.None,String filterValue=null,UserProperty sortProp=UserProperty.None,Boolean sortAscending=true)
{
列表用户=等待此操作。用户
.WhereProperty(filterProp,filterValue)
.OrderByProperty(sortProp、sortAscending)
.ToListAsync()
.配置等待(错误);
List userViewModels=用户
.Select(u=>UserModel.FromUserEntity(u))
.ToList();
返回userViewModels;
}

您可以使用表达式参数:

using System.Linq.Expressions;

//...

private List<UserModel> Search<T>(Expression<Func<UserModel, T>> criteria) 
{
  return Users.Where(criteria).ToList();
}

我发现字典对于保存所有硬编码的内容非常有用:

private Dictionary<string, Func<UserModel, string, bool>> _filters =
    new Dictionary<string, Func<UserModel, string, bool>>()
    {
        { "FirstName", (u, x) => u.FirstName == x },
        { "LastName", (u, x) => u.LastName == x },
        { "DisplayName", (u, x) => u.DisplayName == x },
    };

private void Search(string fieldname, string searchString)
{
    List<UserModel> data = Users.Where(u => _filters[fieldname](u, searchString)).ToList();
}
private Dictionary\u过滤器=
新字典()
{
{“FirstName”,(u,x)=>u.FirstName==x},
{“LastName”,(u,x)=>u.LastName==x},
{“DisplayName”,(u,x)=>u.DisplayName==x},
};
私有无效搜索(字符串字段名、字符串搜索字符串)
{
列表数据=用户。其中(u=>_filters[fieldname](u,searchString)).ToList();
}

欢迎来到SO!请再多描述一下:)这些答案是解决我问题的完美办法。最详细的方法是在这里。@Enigmativity:如果动态搜索条件是基于外部用户数据(字符串)或代码库内部的动态数据(调用方希望使用不同的条件),则有点含糊不清。似乎是后者,尽管您的适用于前者。这不应该是
私有静态只读IReadOnlyDictionary\u过滤器吗?@Dai-这取决于OP是否希望在运行时修改过滤器。
using System.Linq.Expressions;

//...

private List<UserModel> Search<T>(Expression<Func<UserModel, T>> criteria) 
{
  return Users.Where(criteria).ToList();
}
var matches = model.Search(x => x.FirstName == "Bob");
private Dictionary<string, Func<UserModel, string, bool>> _filters =
    new Dictionary<string, Func<UserModel, string, bool>>()
    {
        { "FirstName", (u, x) => u.FirstName == x },
        { "LastName", (u, x) => u.LastName == x },
        { "DisplayName", (u, x) => u.DisplayName == x },
    };

private void Search(string fieldname, string searchString)
{
    List<UserModel> data = Users.Where(u => _filters[fieldname](u, searchString)).ToList();
}