我正在尝试为 FilterDescriptor 构建表达式构建器,我从请求中获得在 DB 中执行,因为它仅在内存中执行。我有数千行从数据库中检索(这就是我创建构建器以减少负载的原因)。
//classes
public class Product
{
public string Name {get;set;}
public TypeOfProduct {get;set;}
}
public class TypeOfProduct
{
public string Description {get;set;}
}
//action Read
public ActionResult Read([DataSourceRequest] DataSourceRequest request)
{
if (request.Filters.Count > 0)
{
where = ApplyFilter(request.Filters[0]);
}
}
// apply the FilterDescriptor to a string
private static string ApplyFilter(IFilterDescriptor filter)
{
var filters = string.Empty;
if (filter is CompositeFilterDescriptor)
{
filters += "(";
var compositeFilterDescriptor = (CompositeFilterDescriptor)filter;
foreach (IFilterDescriptor childFilter in compositeFilterDescriptor.FilterDescriptors)
{
filters += ApplyFilter(childFilter);
filters += string.Format(" {0} ", compositeFilterDescriptor.LogicalOperator.ToString());
}
}
else
{
string filterDescriptor = "{0} {1} {2}";
var descriptor = (FilterDescriptor)filter;
if (descriptor.Operator == FilterOperator.IsEqualTo)
{
System.Linq.Expressions.Expression<Func<Volume, bool>> func = ExpressionExtension.ConvertStringTo<Volume>(member, "=", descriptor.Value.ToString());
}
filters = filterDescriptor;
}
filters = filters.EndsWith("And ") == true ? string.Format("{0})", filters.Substring(0, filters.Length - 4)) : filters;
filters = filters.EndsWith("Or ") == true ? string.Format("{0})", filters.Substring(0, filters.Length - 4)) : filters;
return filters;
}
// Expression Generator
public static class ExpressionExtension
{
public static Expression<Func<T, bool>> ConvertStringTo<T>(string propName, string opr, string value, Expression<Func<T, bool>> expr = null)
{
Expression<Func<T, bool>> func = null;
try
{
PropertyInfo prop = null;
foreach (var x in propName.Split('.'))
{
if (prop == null)
{
prop = typeof(T).GetProperty(x);
}
else
{
prop = prop.PropertyType.GetProperty(x);
}
}
ParameterExpression tpe = Expression.Parameter(typeof(T));
Expression left = Expression.Property(tpe, prop);
Expression right = Expression.Convert(To(prop, value), prop.PropertyType);
Expression<Func<T, bool>> innerExpr = Expression.Lambda<Func<T, bool>>(ApplyFilter(opr, left, right), tpe);
if (expr != null)
{
innerExpr = innerExpr.And(expr);
}
func = innerExpr;
}
catch
{
}
return func;
}
public static Expression<Func<T, TResult>> And<T, TResult>(this Expression<Func<T, TResult>> expr1, Expression<Func<T, TResult>> expr2)
{
var invokedExpr = Expression.Invoke(expr2, expr1.Parameters.Cast<Expression>());
return Expression.Lambda<Func<T, TResult>>(Expression.AndAlso(expr1.Body, invokedExpr), expr1.Parameters);
}
public static Func<T, TResult> ExpressionToFunc<T, TResult>(this Expression<Func<T, TResult>> expr)
{
return expr.Compile();
}
private static Expression To(PropertyInfo prop, string value)
{
object val = Convert.ChangeType(value, ResolveType(prop.PropertyType.ToString()));
return Expression.Constant(val);
}
private static Type ResolveType(String typeName)
{
Type type = Type.GetType(typeName);
if (type == null)
{
return null;
}
Type underlying = Nullable.GetUnderlyingType(type);
if (underlying != null)
{
type = underlying;
}
return type;
}
private static BinaryExpression ApplyFilter(string opr, Expression left, Expression right)
{
BinaryExpression innerLambda = null;
switch (opr)
{
case "=":
innerLambda = Expression.Equal(left, right);
break;
}
return innerLambda;
}
}
问题:如果我的过滤器带有两个字段(“名称”和“描述”),我如何为这两个字段创建连接表达式,因为我需要使用 Product 与 TypeOfProduct 创建连接?
已编辑
return this.Json(this.FactoryDomain.Get().ToDataSourceResult(request, volume => new
{
volume.Id,
volume.ClasseProcessoMarcacao.ClienteId,
volume.ClasseProcessoMarcacao.Cliente.Pessoa.NomeReduzido,
volume.ClasseProcessoMarcacao.NomenclaturaPadrao,
volume.ControleProducaoIdAtual,
volume.CodigoBarras,
volume.NumeroCliente,
volume.NumeroGeral
}));
这是我将数据返回到网格的示例,但如果我过滤“NomeReduzido”属性,则会引发错误。我决定在我的查询中创建过滤器以直接在数据库中执行。