将 Expression<Func<T,bool>> 转换为 Expression<Func<T1,bool>> 以便 T 成为 T1 的成员
Convert an Expression<Func<T,bool>> to an Expression<Func<T1,bool>> so that T is a member of T1
我们有一个 T1
类型的实体,它有一个 T
类型的成员。
像这样:
public class T1
{
public T Member{get;set;}
}
用户可以使用我们的 UI 为我们提供对 T 的过滤器,我们已将其转换为获取 T 和 returns bool (Expression<Func<T,bool>>)
[= 的函数表达式18=]
我想知道是否可以将其转换为获取 T1 和 returns bool 的函数表达式。
其实我想转换这个:
(t=>t.Member1==someValue && t.Member2==someOtherValue);
对此:
(t1=>t1.Member.Member1==someValue && t1.Member.Member2==someOtherValue);
给出
public class MyClass
{
public MyInner Member { get; set; }
}
public class MyInner
{
public string Member1 { get; set; }
public string Member2 { get; set; }
}
加上
public static Expression<Func<TOuter, bool>> Replace<TOuter, TInner>(Expression<Func<TInner, bool>> exp, Expression<Func<TOuter, TInner>> outerToInner)
{
var body2 = new ExpressionReplacer { From = exp.Parameters[0], To = outerToInner.Body }.Visit(exp.Body);
var lambda2 = Expression.Lambda<Func<TOuter, bool>>(body2, outerToInner.Parameters);
return lambda2;
}
和
public class ExpressionReplacer : ExpressionVisitor
{
public Expression From;
public Expression To;
protected override Expression VisitParameter(ParameterExpression node)
{
if (node == From)
{
return base.Visit(To);
}
return base.VisitParameter(node);
}
}
你可以
// The initial "data"
string someValue = "Foo";
string someOtherValue = "Bar";
Expression<Func<MyInner, bool>> exp = t => t.Member1 == someValue && t.Member2 == someOtherValue;
Expression<Func<MyClass, MyInner>> outerToInner = u => u.Member;
// The "new" expression
Expression<Func<MyClass, bool>> result = Replace(exp, outerToInner);
ExpressionReplacer
class 将一个表达式的参数替换为另一个表达式,而 Replace
方法使用 ExpressionReplacer
然后重建一个新表达式。
你可以通过一些方法来完成。
第一个也是最简单的:使用Expression.Invoke
Expression<Func<T, bool>> exprT = t.Member1==someValue && t.Member2==someOtherValue
ParameterExpression p = Expression.Parameter(typeof(T1));
var expr = Expression.Invoke(expr, Expression.PropertyOrField(p, "Member"));
Expression<Func<T1, bool>> exprT1 = Expression.Lambda<Func<T1, bool>>(expr, p);
但在这种情况下你得不到
t1 => (t=>(t.Member1==someValue && t.Member2==someOtherValue))(t1.Member),
而不是
(t1=>t1.Member.Member1==someValue && t1.Member.Member2==someOtherValue);
要替换你可以使用 ExpressionVisitor class like
class V : ExpressionVisitor
{
public ParameterExpression Parameter { get; private set; }
Expression m;
public V(Type parameterType, string member)
{
Parameter = Expression.Parameter(parameterType);
this.m = Expression.PropertyOrField(Parameter, member);
}
protected override Expression VisitParameter(ParameterExpression node)
{
if (node.Type == m.Type)
{
return m;
}
return base.VisitParameter(node);
}
}
并使用它
var v = new V(typeof(T1), "Member");
var exprT1 = Expression.Lambda<Func<T1, bool>>(v.Visit(exprT.Body), v.Parameter);
我们有一个 T1
类型的实体,它有一个 T
类型的成员。
像这样:
public class T1
{
public T Member{get;set;}
}
用户可以使用我们的 UI 为我们提供对 T 的过滤器,我们已将其转换为获取 T 和 returns bool (Expression<Func<T,bool>>)
[= 的函数表达式18=]
我想知道是否可以将其转换为获取 T1 和 returns bool 的函数表达式。
其实我想转换这个:
(t=>t.Member1==someValue && t.Member2==someOtherValue);
对此:
(t1=>t1.Member.Member1==someValue && t1.Member.Member2==someOtherValue);
给出
public class MyClass
{
public MyInner Member { get; set; }
}
public class MyInner
{
public string Member1 { get; set; }
public string Member2 { get; set; }
}
加上
public static Expression<Func<TOuter, bool>> Replace<TOuter, TInner>(Expression<Func<TInner, bool>> exp, Expression<Func<TOuter, TInner>> outerToInner)
{
var body2 = new ExpressionReplacer { From = exp.Parameters[0], To = outerToInner.Body }.Visit(exp.Body);
var lambda2 = Expression.Lambda<Func<TOuter, bool>>(body2, outerToInner.Parameters);
return lambda2;
}
和
public class ExpressionReplacer : ExpressionVisitor
{
public Expression From;
public Expression To;
protected override Expression VisitParameter(ParameterExpression node)
{
if (node == From)
{
return base.Visit(To);
}
return base.VisitParameter(node);
}
}
你可以
// The initial "data"
string someValue = "Foo";
string someOtherValue = "Bar";
Expression<Func<MyInner, bool>> exp = t => t.Member1 == someValue && t.Member2 == someOtherValue;
Expression<Func<MyClass, MyInner>> outerToInner = u => u.Member;
// The "new" expression
Expression<Func<MyClass, bool>> result = Replace(exp, outerToInner);
ExpressionReplacer
class 将一个表达式的参数替换为另一个表达式,而 Replace
方法使用 ExpressionReplacer
然后重建一个新表达式。
你可以通过一些方法来完成。
第一个也是最简单的:使用Expression.Invoke
Expression<Func<T, bool>> exprT = t.Member1==someValue && t.Member2==someOtherValue
ParameterExpression p = Expression.Parameter(typeof(T1));
var expr = Expression.Invoke(expr, Expression.PropertyOrField(p, "Member"));
Expression<Func<T1, bool>> exprT1 = Expression.Lambda<Func<T1, bool>>(expr, p);
但在这种情况下你得不到
t1 => (t=>(t.Member1==someValue && t.Member2==someOtherValue))(t1.Member),
而不是
(t1=>t1.Member.Member1==someValue && t1.Member.Member2==someOtherValue);
要替换你可以使用 ExpressionVisitor class like
class V : ExpressionVisitor
{
public ParameterExpression Parameter { get; private set; }
Expression m;
public V(Type parameterType, string member)
{
Parameter = Expression.Parameter(parameterType);
this.m = Expression.PropertyOrField(Parameter, member);
}
protected override Expression VisitParameter(ParameterExpression node)
{
if (node.Type == m.Type)
{
return m;
}
return base.VisitParameter(node);
}
}
并使用它
var v = new V(typeof(T1), "Member");
var exprT1 = Expression.Lambda<Func<T1, bool>>(v.Visit(exprT.Body), v.Parameter);