我正在构建一个高级搜索屏幕,并使用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>;
这很棒。
我现在正在我的应用程序上构建一个高级搜索屏幕,用户可以在其中搜索一到两个不同的选项以返回匹配的“产品”。即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”的属性的一个项目。但是,如果不编写大量代码,我无法看到如何扩展它。如何在“如果产品金属类型不为空”的行中写下一些代码,添加一个额外的表达式来优化搜索谓词呢?
或者我是否按照构建表达的方式走错了轨道?
提前致谢
答案 0 :(得分:1)
你可以这样做:
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; }
}
这是工作小提琴 - http://dotnetfiddle.net/t0a9yA
基本上,您可以使用所需参数填充Dictionary
,然后根据该字典生成表达式。字典键是属性名称,值是过滤的值。