プロパティを格納するために辞書を使用する一般的なオブジェクトがあります:
class MyObject
{
Dictionary<string, object> Properties = new Dictionary<string, object>();
internal GetValue(string name) { return Properties[name]; }
internal SetValue(string name, object value) { Properties[name] = value; }
}
MyObject obj1 = New MyObject();
obj1.SetValue("Name", "John");
obj1.SetValue("Age", 23);
MyObject obj2 = New MyObject();
obj2.SetValue("Name", "Mary");
obj2.SetValue("Age", 24);
List<MyObject> ObjList = new List<MyObject>();
ObjList.Add(obj1);
ObjList.Add(obj2);
次に、特定のエントリを見つけるためにObjListをクエリする必要があります。動的LINQ( 動的LINQ(パート1:LINQ動的クエリライブラリの使用) )は完璧に見えますが、私が見る限りでは、オブジェクトに事前定義されたプロパティが必要です。
次のようなクエリを実行します。
ObjList.Where("Name == 'Mary' || Age < 24");
トークン(名前、年齢など)は「GetValue」を呼び出す必要があります。助言がありますか?
明らかにwhereステートメントは完全にユーザー次第であり、修正されていません。
C#4.0では、プロパティトークンがそれぞれGetValue()およびSetValue()に解決されるように、 MyObject
にIDynamicMetaDataProvider
インターフェイスを実装させることができます。これで、動的LINQは期待どおりに機能するはずです。
例については、 この投稿を参照してください
動的LINQ拡張メソッドのWhere句のソースは次のとおりです。
public static IQueryable Where(this IQueryable source, string predicate, params object[] values) {
if (source == null) throw new ArgumentNullException("source");
if (predicate == null) throw new ArgumentNullException("predicate");
LambdaExpression lambda = DynamicExpression.ParseLambda(source.ElementType, typeof(bool), predicate, values);
return source.Provider.CreateQuery(
Expression.Call(
typeof(Queryable), "Where",
new Type[] { source.ElementType },
source.Expression, Expression.Quote(lambda)));
}
複雑な部分はDynamicExpression.ParseLambdaビットです。ソースをざっと見てみると、解析コードに「ParseMemberAccess」関数が含まれていることがわかります。この関数は、次のようなことを実行できる可能性があることを示唆しているようです。
ObjList.Where("GetValue('Name') == 'Mary' || GetValue('Age') < 24");
また、パーサーが現在それを許可していない場合は、簡単に拡張して許可することができます。