スキルセットを広げようとして、式を書き直す方法を学ぼうとしています。
目標:List.Contains()
与えられた式で、 のインスタンスを独自の静的メソッドの呼び出しに置き換えたいInList
。たとえば、次の 2 つの式は同等である必要があります。
Expression<Func<Foo,bool>> expr1 = myRewriter.Rewrite(foo => fooList.Contains(foo));
Expression<Func<Foo,bool>> expr2 = foo => InList(foo, fooList);
私の試み:カスタム ExpressionVisitorを使用することが、既存の式に基づいて新しい式を作成する最良の方法であることを学びました。ただし、MethodCallExpression
実際にメソッドを呼び出す新しいものを作成できませんでした。これが私が試したことです:
public class InListRewriter<T> : ExpressionVisitor
{
public static bool InList(T target, List<T> source)
{
// this is my target method
return true;
}
public Expression<Func<T, bool>> Rewrite(Expression<Func<T, bool>> expression)
{
return Visit(expression) as Expression<Func<T,bool>>;
}
protected override Expression VisitMethodCall(MethodCallExpression node)
{
// Only rewrite List.Contains()
if (!node.Method.Name.Equals("Contains", StringComparison.InvariantCultureIgnoreCase))
return base.VisitMethodCall(node);
// Extract parameters from original expression
var sourceList = node.Object; // The list being searched
var target = node.Method.GetParameters()[0]; // The thing being searched for
// Create new expression
var type = typeof (InListRewriter<T>);
var methodName = "InList";
var typeArguments = new Type[] { };
var arguments = new[] { Expression.Parameter(target.ParameterType, target.Name), sourceList };
var newExpression = Expression.Call(type, methodName, typeArguments, arguments);
return newExpression;
}
}
ただし、これを vianew InListRewriter<Foo>().Rewrite(foo => fooList.Contains(foo))
で呼び出すと、InvalidOperationException
duringが発生しExpression.Call
ます。
タイプ 'MyNamespace.InListRewriter`1[MyNamespace.Foo]' のメソッド 'InList' は、指定された引数と互換性がありません。
非常に一般的な署名を使用して、新しい InList を作成しようとさえしました。
public static bool InList(params object[] things) {...}
しかし、それでも同じエラーを受け取りました。私は何を間違っていますか?私がやりたいことは可能ですか?