0

我有以下课程:

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

?

4

3 回答 3

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");
于 2010-03-28T14:27:17.577 回答
1

这与 Linq 动态查询单元没有任何关系。该单元适用于您拥有实际字段/属性的情况,并且它们的名称将在运行时提供给您。换句话说,你有一个这样的类:

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方法才是最重要的,因为否则你会冒一个NullReferenceExceptionifData没有被分配的风险,或者一个KeyNotFoundExceptionif甚至一个Item实例都没有那个属性。GetValue无论如何使用这里的方法都会成功:

var myItems = items.OrderBy(i => i.GetValue(ItemKeys.Name));

如果你发现你正在为相同的属性编写大量重复的代码,那么就开始担心向类中添加快捷方式属性或扩展方法。

于 2010-03-28T14:54:18.853 回答
0

我假设您在编译时不知道属性的名称(在这种情况下,您可以简单地定义属性并且不会遇到这个问题)。我有两个建议你可以尝试,但我自己没有实施任何一个,所以我不能保证它会起作用。

  • 如果可以使用 .NET 4.0,则可以继承DynamicObject并实现TryGetMember方法(o.Foo在声明为 的对象上使用时会调用该方法dynamic)。假设 Dynamic LINQ 与 DLR 一起使用,它应该自动为继承自DynamicObject. 在该TryGetMember方法中,您将获得访问属性的名称,因此您可以执行字典查找。(但是,此解决方案仅在 Dynamic LINQ 与 DLR 很好地集成时才有效)。

  • 在任何情况下,您都可以对用户输入的字符串进行一些基本解析,并替换为Name例如Data["Name"]. 这肯定会起作用,但可能有点困难(因为您可能至少应该检查您是否在正确的上下文中进行替换 - 例如不在字符串常量内)。

关于扩展方法 - 我不确定动态 LINQ 是否处理扩展方法(但是,我不这么认为,因为这需要搜索所有引用的程序集)

于 2010-03-28T14:35:16.167 回答