c# - 如何为高级搜索屏幕构建自定义表达式

标签 c# search lambda expression

我正在构建一个高级搜索屏幕并使用 nHibernate 查询数据库。我已经构建了我的 DataAccess 层并构建了一个非常有效的通用方法 - 我传入一个用作谓词的表达式并传回与该谓词匹配的对象集合:

public object LoadByPredicate<T>(Expression<Func<T, bool>> predicate) where T : class

示例用法是:

var items = _query.LoadByPredicate<StaticTypes>(x => x.StaticName == type) as List<StaticTypes>;

这太棒了。

我现在正在我的应用程序上构建一个高级搜索屏幕,用户可以在其中搜索 1 到 20 个不同的选项以返回匹配的“产品”。 IE。 Product 类有 20 个属性,它们可以通过 Name、Reference、Description、Value 等的组合进行搜索......

我想构建一种机制,为我构造一个表达式,我可以将其传递到上面的“LoadByPredicate”方法中。

到目前为止,我证明这是可行的:

var type = typeof(Model.Product);
var property = type.GetProperty("ProductMetalProductType");
var parameter = Expression.Parameter(typeof(Model.Product), "x");

Expression<Func<Model.Product, bool>> predicate =
     (Expression<Func<Model.Product, bool>>)Expression.Lambda(
        Expression.Equal(
            Expression.MakeMemberAccess(parameter, property),
           Expression.Constant(metalProdType)),
                parameter);

这对于名为“ProductMetalProductType”的属性的一项非常有效。但是,我看不出如何在不编写大量代码的情况下扩展它。我如何编写一些代码,在“如果产品金属类型不为空”行中添加一个额外的表达式来优化搜索谓词?

还是我构建表达式的方式走错了路?

提前致谢

最佳答案

你可以这样做:

public class Program
{
    static void Main(string[] args)
    {
        var parameters = new Dictionary<string, object>();
        parameters.Add("ProductMetalProductType", 1);
        parameters.Add("IsActive", true);
        parameters.Add("Name", "New cool product");

        var expr = GenerateExpression<Product>(parameters);
        Console.WriteLine("Result expression:");
        Console.WriteLine(expr.ToString());
    }

    private static Expression<Func<T, bool>> GenerateExpression<T>(Dictionary<string, object> properties)
    {
        var type = typeof(T);
        List<Expression> expressions = new List<Expression>();
        var parameter = Expression.Parameter(typeof(T), "x");
        foreach (var key in properties.Keys)
        {
            var val = properties[key];
            var property = type.GetProperty(key);

            var eqExpr = Expression.Equal(Expression.MakeMemberAccess(parameter, property), Expression.Constant(val));

            expressions.Add(eqExpr);
        }

        Expression final = expressions.First();
        foreach (var expression in expressions.Skip(1))
        {
            final = Expression.And(final, expression);
        }

        Expression<Func<T, bool>> predicate =
            (Expression<Func<T, bool>>) Expression.Lambda(final, parameter);

        return predicate;
    }
}

public class Product
{
    public int ProductMetalProductType { get; set; }

    public bool IsActive { get; set; }

    public string Name { get; set; }
}

这是工作 fiddle - http://dotnetfiddle.net/t0a9yA

基本上你可以用需要的参数填充Dictionary,然后根据那个字典生成表达式。 Dictionary key为属性名,value为过滤值。

关于c# - 如何为高级搜索屏幕构建自定义表达式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21801702/

相关文章:

c# - 问潜在员工的 C# ASP.NET MVC 问题是什么?

python - 获取 Python 函数并生成所有导数

c# - 如何在Elasticsearch charFilter中两次映射相同的字符

c# - 为所有用户部署 VSTO 加载项

ruby-on-rails - Sunspot Solr 不使用简单范围

search - 搜索引擎的相关性排名和推荐系统之间的区别

java - 过滤功能不偷懒

c# - 无法解析 Enumerable 和 Queryable 候选人之间的方法

c# - Windows Phone 7 的 Protocol Buffer 网络

java - 在 Java 上搜索 Vector 内的属性