次のコードは説明不要でしょう。And
演算子を使用して 2 つの式を 1 つに結合したいのです。最後の行で rune-time にエラーが発生します。
追加情報: 'System.String' 型の変数 'y' がスコープ '' から参照されていますが、定義されていません
コード:
Expression<Func<string, bool>> e1 = y => y.Length < 100;
Expression<Func<string, bool>> e2 = y => y.Length < 200;
var e3 = Expression.And(e1.Body, e2.Body);
var e4 = Expression.Lambda<Func<string, bool>>(e3, e1.Parameters.ToArray());
e4.Compile(); // <--- causes run-time error
ベストアンサー1
他の回答に示されているように、 という名前のパラメータを持つ 2 つの式がありますy
。それらは自動的に相互に関連付けられるわけではありません。
式を適切にコンパイルするには、ソース式の両方のパラメータを指定する必要があります。
Expression<Func<string, bool>> e1 = (y => y.Length > 0);
Expression<Func<string, bool>> e2 = (y => y.Length < 5);
var e3 = Expression.And(e1.Body, e2.Body);
// (string, string) by adding both expressions' parameters.
var e4 = Expression.Lambda<Func<string, string, bool>>(e3, new[]
{
e1.Parameters[0],
e2.Parameters[0]
});
Func<string, string, bool> compiledExpression = e4.Compile();
bool result = compiledExpression("Foo", "Foo");
もちろん、両方の式を 1 つのパラメータのみで組み合わせた式が必要になります。次のように式を再構築できます。
ParameterExpression param = Expression.Parameter(typeof(string), "y");
var lengthPropertyExpression = Expression.Property(param, "Length");
var e1 = Expression.GreaterThan(lengthPropertyExpression, Expression.Constant(0));
var e2 = Expression.LessThan(lengthPropertyExpression, Expression.Constant(5));
var e3 = Expression.AndAlso(e1, e2);
var e4 = Expression.Lambda<Func<string, bool>>(e3, new[] { param });
Func<string, bool> compiledExpression = e4.Compile();
bool result = compiledExpression("Foo");
式を再構築するのではなく、既存の式の本体とパラメータで実行するというコメントについては、これは次ExpressionRewriter
のように機能します。C# で 2 つのラムダ式を組み合わせるそしてAndAlso
から式の本体のパラメータ名を置き換える:
Expression<Func<string, bool>> e1 = (y => y.Length > 0);
Expression<Func<string, bool>> e2 = (z => z.Length < 10);
var e3 = ParameterReplacer.AndAlso<string>(e1, e2);
Func<string, bool> compiledExpression = e3.Compile();
bool result = compiledExpression("Foo");