动态Linq库帮助

时间:2010-03-28 14:16:19

标签: c# linq dynamic-linq

我有以下课程:

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")

3 个答案:

答案 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是否处理扩展方法(但是,我不这么认为,因为这需要搜索所有引用的程序集)