オブジェクトがあります
public class SomeObject
{
public Name {get;set;}
public City {get;set;}
public State {get;set}
//various other parameters. Let's say there's ~20
}
ソースコードを再コンパイルせずに、新しいLINQクエリを動的に作成することは可能ですか?代わりに、クエリパラメータは、データベースに格納および更新されるXML構造から取得されます。
var result = from i in someObj
where
//XML requests Name = 'Bob'...so append this where clause
name = 'Bob'
これはできますか?
式ツリーを使用したソリューションは次のとおりです。
var param = Expression.Parameter(typeof(SomeObject), "p");
var exp = Expression.Lambda<Func<SomeObject, bool>>(
Expression.Equal(
Expression.Property(param, "Name"),
Expression.Constant("Bob")
),
param
);
var query = someObj.Where(exp);
私はそれがはるかに複雑であることを知っていますが、これは時には役立つかもしれません。
Dynamic Linq を見てください。これにより、クエリ条件をテキストとして定義できます。
条件を動的に追加する場合、同様の構文を使用して条件をクエリに追加できます。
if(CategoryIsImportant)
myQuery = myQuery.Where("CategoryId=2");
これらはすべて、選択したXML形式に(かなり簡単に)エンコードできます。
あなたの質問に基づいて伝えるのは難しいですが、場合によっては動的なLinqを必要とせず、単にこれを行うことができます...
var result = from o in someObj
where (Name == null || o.Name == Name)
&& (City == null || o.City == City)
&& (State == null || o.State == State)
select o;
これにより、問題のパラメーターがnullの場合に、データがフィルターされなくなります。そして、C#の短絡動作のおかげで、まだうまく機能しています。
Expression Trees を実際に掘り下げる必要があると思います。あまり掘り下げていないので、サンプルを作成することはできませんが、Expression Treeを使用してクエリを動的に構築し、.Compile(コード内)を呼び出して実行できることを知っています。
実際、こちらがより良いリンクです 式ツリーを使用した動的クエリの構築 。それはあなたが望むものを正確に与えるべきであり、それが何であるかについてかなり簡潔です。これはあなたのための良い例として機能するはずです:)
多分Dynamic Linqがあなたを助けることができます: Dynamic linqパート1:linq動的クエリライブラリの使用
query = query.Where("Id = 123 And Age > 18");
または、Linqクエリを直接操作できます。
query = query.Where(x=>x.Id == 5);
XMLのコンテンツに応じて、オプションのフィルターを導入することを想定しています。 StriplingWarriorの例を続けるには:
var name = GetNameFromXml();
var city = GetCityFromXml();
var state = GetStateFromXml();
var result = someObj;
if (name != null)
result = result.Where(i => i.Name == name);
if (city != null)
result = result.Where(i => i.City == city);
if (state != null)
result = result.Where(i => i.State == state);
この方法では、XMLで実際に指定されている内容に応じて、任意の数のフィルター(なしから3つすべてまで)を適用します。
はい、実際には非常に簡単です。
var name = GetBobNameFromXml();
var result = someObj.Where(i => i.Name == name);
基準を少しずつ適用するかどうかも選択できます。
var result = someObj;
var name = xmlCriteria.Name;
if(!string.IsNullOrEmpty(name))
{
result = result.Where(i => i.Name == name);
}
// follow the same pattern for city, state, etc.
if
ステートメントの束を回避するために、基準関数の名前キー付き辞書を使用するパターンを使用することもできます。
foreach(var criterionPair in xmlCriteria)
{
var value = criterionPair.Value;
result = result.Where(i => propGetters[criterionPair.PropertyName](i, value));
}
基本的に、これらの線に沿ってできることはたくさんあります。より具体的に自分の状況に合わせた回答が必要な場合は、より具体的な質問を提供する必要があります。