我想防止重复用于ORM中联接/关联双方的相同谓词逻辑。我应该:
1)使用Func<T1, T2, bool>
并使用扩展方法来获取表达式:
public static Expression<Func<T1, T2, bool>> ExpressionFuncT1T2<T1, T2>(this Func<T1, T2, bool> func) => (t1, t2) => func(t1, t2);
public static Expression<Func<T2, T1, bool>> ExpressionFuncT2T1<T1, T2>(this Func<T1, T2, bool> func) => (t1, t2) => func(t2, t1);
或
2)使用Expression<Func<T1, T2, bool>>
的一侧,并根据此stackoverflow question的答案将其转换为Expression<Func<T2, T1, bool>>
,如下所示:
public static Expression<Func<T2, T1, bool>> WhatToCallThis<T1,T2>(
this Expression<Func<T1, T2, bool>> predicate) {
var t1 = Expression.Parameter(typeof(T1), "t1");
var t2 = Expression.Parameter(typeof(T2), "t2");
return Expression.Lambda<Func<T2, T1, bool>>(
Expression.Invoke(predicate,
Expression.PropertyOrField(t2, "T1"),
Expression.PropertyOrField(t1, "T2")
), t2, t1);
}
您还要给这个方法命名吗?
答案 0 :(得分:0)
似乎下面所有的3种方法都可以使用,但是在性能上最好使用哪种方法?
SwapParameters1使用 Expression.Lambda :
public static Expression<Func<T2, T1, TResult>> SwapParameters1<T1, T2, TResult>
(this Expression<Func<T1, T2, TResult>> exprFunc)
=> Expression.Lambda<Func<T2, T1, TResult>>(exprFunc.Body
, exprFunc.Parameters[1]
, exprFunc.Parameters[0]);
SwapParameters2使用 .Compile():
public static Expression<Func<T2, T1, TResult>> SwapParameters2<T1, T2, TResult>
(this Expression<Func<T1, T2, TResult>> exprFunc)
=> (t1, t2) => exprFunc.Compile()(t2, t1);
SwapParameters3使用 ExpressionVisitor 替换参数(此so问题帮助了):
public static Expression<Func<T2, T1, TResult>> SwapParameters3<T1, T2, TResult>
(this Expression<Func<T1, T2, TResult>> exprFunc) {
var param1 = Expression.Parameter(typeof(T1));
var param2 = Expression.Parameter(typeof(T2));
return Expression.Lambda<Func<T2, T1, TResult>>(exprFunc.Body
.Replace(exprFunc.Parameters[0], param1)
.Replace(exprFunc.Parameters[1], param2)
, param1, param2);
}
public static Expression<Func<TNewParam, TResult>> ReplaceParameter<TNewParam, TOldParam, TResult>
(this Expression<Func<TOldParam, TResult>> expression)
where TNewParam : TOldParam {
var param = Expression.Parameter(typeof(TNewParam));
return Expression.Lambda<Func<TNewParam, TResult>>(
expression.Body.Replace(expression.Parameters[0], param)
, param);
}
public class ReplaceVisitor : ExpressionVisitor {
private readonly Expression from, to;
public ReplaceVisitor(Expression from, Expression to) {
this.from = from;
this.to = to;
}
public override Expression Visit(Expression node) => node == from ? to : base.Visit(node);
}
public static Expression Replace(this Expression expression, Expression searchExpression, Expression replaceExpression)
=> new ReplaceVisitor(searchExpression, replaceExpression).Visit(expression);
我倾向于使用SwapParameters1。