左側と右側のプロパティ (オペランド) を表す 2 つ (または必要に応じて 4 つ) のラムダを受け取り、述語を生成する関数を記述して、「メタ述語」を作成することは可能ですか。次のコード サンプルのようなもの:
public Expression<Func<Something,bool>> StringEquals<Something>(Expression<Something> leftOperand, Expression<Something> leftOperandSelector){
return (rightOperandSelector, leftOperandSelector) => (
(rightOperandSelector == leftOperandSelector)
|| (
string.IsNullOrEmpty(rightOperandSelector) &&
string.IsNullOrEmpty(leftOperandSelector)
)
);
}
また:
public Expression<Func<Something,bool>> DatesActive<Something>(Expression<Something> startDateOperandSelector, Expression<Something> endDateOperandSelector){
return (startDateOperandSelector, endDateOperandSelector) => (
(startDatePropertySelector >= DateTime.Now)
&& (endDatePropertySelector <= DateTime.Now)
);
}
各側の SomeStringProperty またはstartDatePropertySelectorまたはendDatePropertySelectorがラムダによって定義されている場所は? 述語式のオペランドを動的に渡す方法がわかりません。
理想的には、次のようにインライン化できるようにしたいと考えています。
return new Expression<Func<Request,bool>>[]{
r => (r.Id != request.Id) && (!r.Reviewed),
StringEquals(r => r.VendorName, request=>request.VendorName),
NotExpired(r => r.ContractStart, request=>request.ContractEnd),
...
};
*誰かがこれにアプローチする最善の方法についてアイデアを持っていますか? 私の関心は、複数のプロパティで同じ式を繰り返し使用している場合に、簡単に使用できる「メタ」式を作成することです。参照/説明のために具体的な例を示します。これがばかげているかどうか、そしてより良いアプローチがあるかどうかを知ることに非常にオープンであり、喜んで学びます。*
必要に応じて、以下に背景を追加します。
背景:この Expression のより単純な形式が整った後、次のように C# を解釈する代わりに、EntityFramework が同等性を期待どおりに処理しないという事実を処理するために、リファクタリングを余儀なくされました
(rightSide.SomeStringProperty == leftSide.SomeStringProperty)
。
(
(rightSide.SomeStringProperty IS NULL AND leftSide.SomeStringProperty IS NULL)
OR (rightSide.SomeStringProperty = leftSide.SomeStringProperty)
)
より文字通りに翻訳すると、次のようになります。
(rightSide.SomeStringProperty = leftSide.SomeStringProperty)
もちろん、両側がnullの場合は値を返しません。どうやらこれは EF6 で修正されているようです (修正: @Slauma は、これは UseCSharpNullComparisonBehavior を介して EF5 で利用できることを指摘しています。私は EF4 を使用しており、このリリースにアップグレードすることはできません。)
次のようなコードの繰り返しは避けたいです。
var where = new Expression<Func<Request,bool>>[]{
r => (r.Id != request.Id) && (!r.Reviewed)
&& (
(r.Address == request.Address)
|| (string.IsNullOrEmpty(r.Address) && string.IsNullOrEmpty(request.Address))
)
&& (
(r.City == request.City)
|| (string.IsNullOrEmpty(r.City) && string.IsNullOrEmpty(request.City))
)
&& (
(r.Province == request.Province)
|| (string.IsNullOrEmpty(r.Province) && string.IsNullOrEmpty(request.Province))
)
&& (
(r.PostalCode == request.PostalCode)
|| (string.IsNullOrEmpty(r.PostalCode) && string.IsNullOrEmpty(request.PostalCode))
)
&& (
(r.Website == request.Website)
|| (string.IsNullOrEmpty(r.Website) && string.IsNullOrEmpty(request.Website))
)
};