我正在构建一个高级搜索屏幕并使用 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/