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