我有一个使用字典存储属性的通用对象:
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中,您可以使MyObject
实现IDynamicMetaDataProvider
接口,以便属性标记分别解析为GetValue()和SetValue()。动态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");
而且,如果解析器当前不允许这样做,则可以轻松地对其进行扩展以使其能够。