过滤器设计中的 Linq 铸造
Posted
技术标签:
【中文标题】过滤器设计中的 Linq 铸造【英文标题】:Linq casting in a Filter design 【发布时间】:2022-01-09 11:23:31 【问题描述】:我正在尝试创建一个可以传递给存储库的规范类。该规范有 2 个部分,Where 子句(效果很好)和过滤器,每当您按类型不是字符串的属性进行排序时,它都会给我一个错误。
public class Specification<T> where T : class
public Expression<Func<T, bool>>? Where get; init;
public Filter<T>? Filter get; init;
public class Filter<T>
where T : class
public IOrderBySelector<T>? OrderBy get; init;
public IList<IOrderBySelector<T>> ThenBy get; = new List<IOrderBySelector<T>>();
public bool Paginated get; set;
public int ItemsPerPage get; init;
public int CurrentPage get; init;
我已将错误原因隔离到 OrderSelector。过滤器将选择器表达式 'Expression
public interface IOrderBySelector<T> where T : class
OrderByDirection Direction get;
LambdaExpression? Selector get;
Type? SelectorType get;
public class OrderBySelector<T, TKey> : IOrderBySelector<T>
where T : class
where TKey : notnull
public OrderByDirection Direction get; init;
public Expression<Func<T, TKey>>? Selector get; init;
public Type? SelectorType
get
var body = Selector.Body;
// Unwrap the conversion to object, if there is one.
if (body.NodeType == ExpressionType.Convert)
body = ((UnaryExpression)body).Operand;
return body.Type;
LambdaExpression? IOrderBySelector<T>.Selector
get
if (this.Selector == null) return null;
return (LambdaExpression)this.Selector;
我能做的最好的事情就是在 Linq 查询中尝试使用选择器并将其转换回其真实类型时对其进行询问。
评估规范的方法的一部分:
foreach (IOrderBySelector<Company> thenOrderBy in spec.Filter.ThenBy)
switch (thenOrderBy.SelectorType.FullName)
case "System.String":
query = orderdQuery.ThenBy<Company, string>((Expression<Func<Company, string>>)thenOrderBy.Selector);
break;
case "System.Int32":
query = orderdQuery.ThenBy<Company, int>((Expression<Func<Company, int>>)thenOrderBy.Selector);
break;
case "System.Int64":
query = orderdQuery.ThenBy<Company, long>((Expression<Func<Company, long>>)thenOrderBy.Selector);
break;
case "System.Guid":
query = orderdQuery.ThenBy<Company, Guid>((Expression<Func<Company, Guid>>)thenOrderBy.Selector);
break;
case "System.Decimal":
query = orderdQuery.ThenBy<Company, decimal>((Expression<Func<Company, decimal>>)thenOrderBy.Selector);
break;
default:
throw new NotImplementedException($"thenOrderBy.SelectorType.FullName");
如何在执行之前重建表达式,或者在执行查询之前将 Selector 的类型从对象更改回适当的类型。
欢迎任何帮助。
谢谢
【问题讨论】:
【参考方案1】:您可以通过构建表达式树来做到这一点。我已将Company
替换为通用参数T
// just extract expression
var queryExpression = query.Expression;
foreach (var thenOrderBy in spec.Filter.ThenBy)
var orderLambda = thenOrderBy.Selector;
// here we dynamically create ThenBy
var queryExpression = Expression.Call(typeof(Queryable), nameof(Queryable.ThenBy),
new [] typeof(T), orderLambda.ReturnType,
queryExpression, orderLambda);
// apply to query
query = query.Provider.CreateQuery<T>(queryExpression);
【讨论】:
以上是关于过滤器设计中的 Linq 铸造的主要内容,如果未能解决你的问题,请参考以下文章