AFAIK BCL은 표현식 작업에 대한 지원이 매우 제한되어 있습니다. 메서드 매개 변수 유형을 변경하려면 직접 표현식을 다시 작성해야 할 것입니다.
어렵지는 않지만 쉬운 것도 아닙니다. 기본적으로 Expression
(모든 트리)의 모든 노드를 복제하지만 루트 노드의 데이터 유형은 Func<TImplementation, bool>
으로 설정합니다.
같은 목표를 달성했지만 다른 주조 요구 사항이없는 다른 디자인을 찾아 볼 것입니다. 표현을 통해 갈고 닦는 것은 재미 있지 않습니다.
업데이트 나는 원하는대로 기능을 구현했습니다. 그것은이하는 모든 새로운 유형의 이전 ParamaterType 대체 표현을 재 작성
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();
}
}
: 나는 그것을 CastParam
를 호출합니다.
예상대로
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);
}
:
코드는 내가 쓴
Expression
라이터에 의존
False
True
은 (아래에서 위로 식 트리를 재 작성)
재 작성자가 분명히 불완전하기 때문에 완료해야합니다.
빠른 답변을 주셔서 감사합니다. 나는 두려웠습니다. (누군가에게 몇 가지 대안 아이디어가있는 경우에 대비해 다른 질문을 던지기로하겠습니다.) – roundcrisis
또한 결국에는 현상금을 설정할 수 있습니다. :-) –
나는이 인터페이스를 구현하는 private 클래스를 가지고 있으며 setted 속성에서 다시 만들었다. 약간의 코드 라인을 가지고 있지만별로 끔찍하지 않다. 그것으로 행복해 오늘 오늘 작은 발표를 다시해야 할 것입니다 – roundcrisis