AFAIK BCL对使用表达式的支持非常有限。我担心你将不得不重写表达式来改变方法参数类型。它不难,也不容易。基本上,您将克隆Expression
(它是一棵树)的每个节点,但将根节点的数据类型设置为Func<TImplementation, bool>
。
我会寻找一个完成相同目标但不具备此铸造要求的不同设计 - 翻阅表达式并不好玩。
更新我已经实现了一个你想要的功能。我把它叫做CastParam
:
public static Expression<Func<TOut, bool>> CastParam<TIn, TOut>(this Expression<Func<TIn, bool>> inExpr) {
if (inExpr.NodeType == ExpressionType.Lambda &&
inExpr.Parameters.Count > 0) {
var inP = inExpr.Parameters[0];
var outP = Expression.Parameter(typeof(TOut), inP.Name);
var outBody = inExpr.Body.ConvertAll(
expr => (expr is ParameterExpression) ? outP : expr);
return Expression.Lambda<Func<TOut,bool>>(
outBody,
new ParameterExpression[] { outP });
}
else {
throw new NotSupportedException();
}
}
它所做的就是重写表达与新型替代旧ParamaterType。这里是我的小测试:
class TInterface { public int IntVal; }
class TImplementation : TInterface { public int ImplVal; }
void Run()
{
Expression<Func<TInterface, bool>> intExpr = (i => i.IntVal == 42);
Expression<Func<TImplementation, bool>> implExpr = intExpr.CastParam<TInterface, TImplementation>();
Console.WriteLine ("{0} --> {1}", intExpr, implExpr);
var c = implExpr.Compile();
Console.WriteLine (c.Invoke (new TImplementation { IntVal = 41, ImplVal = 42 }));
Console.WriteLine (c.Invoke (new TImplementation { IntVal = 42, ImplVal = 41 }));
}
正如预期的那样,它打印:
public static Expression Rewrite(this Expression exp, Func<Expression, Expression> c) {
Expression clone = null;
switch (exp.NodeType) {
case ExpressionType.Equal: {
var x = exp as BinaryExpression;
clone = Expression.Equal(Rewrite(x.Left,c), Rewrite(x.Right,c), x.IsLiftedToNull, x.Method);
} break;
case ExpressionType.MemberAccess: {
var x = exp as MemberExpression;
clone = Expression.MakeMemberAccess(Rewrite(x.Expression,c), x.Member);
} break;
case ExpressionType.Constant: {
var x = exp as ConstantExpression;
clone = Expression.Constant(x.Value);
} break;
case ExpressionType.Parameter: {
var x = exp as ParameterExpression;
clone = Expression.Parameter(x.Type, x.Name);
} break;
default:
throw new NotImplementedException(exp.NodeType.ToString());
}
return c(clone);
}
:
False
True
代码依赖于Expression
重写,我写(从下往上重写表达式树)
重写器显然是不完整的,你需要完成它。
感谢您的快速回答,我很害怕那个:(。我会住另一个问题,以防万一别人有一些替代想法 – roundcrisis 2009-11-19 19:28:01
绝对可以,最终你可以设置一个赏金,也许有人会为你写代码:-) – 2009-11-19 20:02:00
感谢你们,我做了一些稍微不同的事情(我有一个私人类,它实现了接口,我从设置的属性中重新创建了它,它只是几行代码,但我不是非常糟糕对此感到满意,所以今天过后我不得不重新考虑这个问题(小今天发布) – roundcrisis 2009-11-20 11:24:14