我有以下课程:
public class Item
{
public Dictionary<string, string> Data
{
get;
set;
}
}
及其清单:
List<Item> items;
我需要使用类似SQL的字符串动态过滤和排序此列表。问题是,我需要通过数据字典订购它。
例如:Order By Data["lastname"]
或Where Data["Name"].StartsWith("a")
。我想使用动态linq库,但有没有我的客户可以在没有Data []的情况下编写的方法?例如:
Name.StartsWith("abc")
而不是
Data["Name"].StartsWith("abc")
答案 0 :(得分:1)
您可以添加如下属性:
public class Item
{
public Dictionary<string, string> Data
{ get; set; }
public string Name { get { return Data["lastname"]; } }
}
//Call by: i.Name.StartsWith("abc");
或扩展方法:
public static class ItemExtensions
{
public static string Name(this Item item)
{
return item.Data["lastname"];
}
}
//Call by: i.Name().StartsWith("abc");
或者,如果它是非常常用方法,您可以添加类似.NameStartsWith()
的内容:
public static string NameStartsWith(this Item item, stirng start)
{
return item.Data["lastname"].StartsWith(start);
}
//Call by: i.NameStartsWith("abc");
答案 1 :(得分:1)
这与Linq Dynamic Query单元无关。当您拥有实际字段/属性时,该单位将用于运行时将提供给您的名称。换句话说,你有一个这样的类:
public class Person
{
public int ID { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
}
您希望能够编写如下查询:
var sortedPeople = people.OrderBy("FirstName");
您正在尝试与此完全相反 - 您有一个没有任何实际属性的类,只有一个属性字典,并且您希望编译时安全。你不能拥有它;当字典是公开的并且任何人都可以直接添加/删除项目时,无法保证项目将在字典中,尤其!
如果有某种原因你必须使用那个特定的类设计,那么你可以想象写一些包装,就像尼克提出的那样,但我甚至都不打扰 - 他们实际上并没有提供任何包装封装,因为Data
字典仍然对全世界开放。相反,我只提供一个安全 getter方法或索引器属性,并创建一些常量(或枚举),其中包含您希望在那里的属性的名称。
public class Item
{
public Dictionary<string, string> Data { get; set; }
public string GetValue(string key)
{
if (Data == null)
return null;
string result;
Data.TryGetValue(key, out result);
return result;
}
}
public class ItemKeys
{
public const string Name = "Name";
public const string Foo = "Foo";
}
等等。实际上ItemKeys
并不重要,安全GetValue
方法非常重要,否则如果NullReferenceException
尚未分配,则会冒Data
的风险,或KeyNotFoundException
如果甚至一个Item
实例没有该属性。无论如何,使用GetValue
方法都将成功:
var myItems = items.OrderBy(i => i.GetValue(ItemKeys.Name));
如果您发现正在为相同的属性编写大量重复代码,则开始担心将快捷方式属性或扩展方法添加到类中。
答案 2 :(得分:0)
我假设您在编译时不知道属性的名称(在这种情况下,您可以简单地定义属性并且不会出现此问题)。我有两个你可以尝试的建议,但我自己没有实现任何一个,所以我不能保证它会起作用。
如果您可以使用.NET 4.0,则可以继承DynamicObject
并实现TryGetMember
方法(当您在声明为的对象上使用o.Foo
时调用该方法dynamic
)。假设Dynamic LINQ与DLR一起使用,它应该自动为从DynamicObject
继承的对象调用此方法。在TryGetMember
方法中,您将获得被访问属性的名称,因此您可以执行字典查找。 (但是,只有当Dynamic LINQ与DLR很好地集成时,此解决方案才有效。)
在任何情况下,您都可以对用户输入的字符串进行一些基本解析,并将Name
替换为Data["Name"]
。这肯定会有用,但可能有点困难(因为你应该至少检查一下你是否在正确的上下文中进行替换 - 例如不在字符串常量内)。
关于扩展方法 - 我不确定Dynamic LINQ是否处理扩展方法(但是,我不这么认为,因为这需要搜索所有引用的程序集)