从平面列表中提取嵌套对象结构

时间:2014-12-08 20:19:57

标签: c# linq tree

我有一个看起来像这样的对象列表:

public class AllTablesView
{
    public string ClientId { get; set; }
    public string ClientName { get; set; }
    public string ContractNumber { get; set; }
    public string ContractDate { get; set; }
    public string OrderId { get; set; }
    public string CarColor { get; set; }
    public string CarPlateNumber { get; set; }
    public string InvoiceType { get; set; }
    public string InvoiceValue { get; set; }
}

实际的类比这大,具有至少12个不同实体的属性,转换后它们应该如下所示:

public class Client
{
    public string ClientId { get; set; }
    public string ClientName { get; set; }
    public IEnumerable<Contract> Contracts { get; set; }
}

public class Contract
{
    public string ContractNumber { get; set; }
    public string ContractDate { get; set; }
    public IEnumerable<Order> Orders { get; set; }
}

public class Car 
{
    public string CarColor { get; set; }
    public string CarPlateNumber { get; set; }
    public IEnumerable<Invoice> Invoices { get; set; }
}

public class Invoice
{
    public string InvoiceType { get; set; }
    public string InvoiceValue { get; set; }
}

就像我说的那样,这有点过分,但结构是一样的。我想知道如何从“AllTablesView”类中提取嵌套对象结构。

我试图使用Linq的Group By,但后来我必须按每个实体进行分组然后循环,考虑到实体的数量,这是不切实际的。

一个注意事项是我在创建一些对象时有一些逻辑,例如:发票类型是根据客户端ID定义的。

编辑: 我忘了一件事,可能会影响答案。填充这些属性的数据来​​自数据库,未进行分组。这意味着客户端ID将重复多次,但它本质上是相同的客户端,因此我无法再次创建它。对于我在这里曝光的每个实体都是如此,发票可能不是那么多。

目标是创建一个json文件,其中包含这个“树”,没有重复。

2 个答案:

答案 0 :(得分:1)

我不知道从另一个类中自动提取类的方法。您可以尝试添加扩展方法,而不是提取所需的信息,例如:

public static class ExtensionMethods
{
    public static Client GetClient(this AllTablesView view)
    {
        return new Client()
                   {
                       ClientID = view.ClientID,
                       ClientName = view.ClientName,
                   };
    }
}

然后让你的课程看起来更简单:

Client client = myAllTableView.GetClient();

可能不是你希望的答案,但除了一些代码自动生成工具之外,我不认为LINQ必须在这里提供帮助。

修改:对于手动分组,您可以尝试使用以下内容检查它是否已存在:

Dictionary<int, Client> clients = new Dictionary<int, Client>();

foreach (AllTableView tableView in AllTableViewCollection)
{
    if (clients.ContainsKey(tableView.ClientID) == false)
    {
        clients.Add(tableView.GetClient());
    }
}

这当然是自己做的。其他人可能有更好的想法通过LINQ实现自动化。

答案 1 :(得分:1)

表示嵌套对象结构的另一种方法是使用XML。因此,例如,您可以轻松地构建一个表示客户端及其相应合同的XML字符串,如下所示:

XElement xeBody =
    new XElement("Clients",

       // for each client in the list of all tables
       from client in lstAllTables
       //...group by client id into client group
       group client by client.ClientId into clientGroup
        //... for each client int the group create a <Client> element 
        select new XElement("Client",
           new XAttribute("ClientId", clientGroup.First().ClientId),
           new XAttribute("ClientName", clientGroup.First().ClientName),

           // for each contract in the current client group create a <Contract> element
           from contract in clientGroup
           select new XElement("Contract",
              new XAttribute("ContractNumber", contract.ContractNumber),
              new XAttribute("ContractDate", contract.ContractDate)
           )
       )
   );

以此为输入:

List<AllTablesView> lstAllTables = new List<AllTablesView>()
{                
    new AllTablesView() { ClientId = "1", ClientName = "Bob", ContractNumber = "BC1001", ContractDate = "2014-12-07" },
    new AllTablesView() { ClientId = "1", ClientName = "Bob", ContractNumber = "BC1002", ContractDate = "2014-12-08" },
    new AllTablesView() { ClientId = "1", ClientName = "Bob", ContractNumber = "BC1003", ContractDate = "2014-12-08" },
    new AllTablesView() { ClientId = "2", ClientName = "Jim", ContractNumber = "AD1003", ContractDate = "2014-12-08" },
    new AllTablesView() { ClientId = "2", ClientName = "Jim", ContractNumber = "AD1004", ContractDate = "2014-12-08" }
};

您将获得以下XML:

<Clients>
  <Client ClientId="1" ClientName="Bob">
    <Contract ContractNumber="BC1001" ContractDate="2014-12-07" />
    <Contract ContractNumber="BC1002" ContractDate="2014-12-08" />
    <Contract ContractNumber="BC1003" ContractDate="2014-12-08" />
  </Client>
  <Client ClientId="2" ClientName="Jim">
    <Contract ContractNumber="AD1003" ContractDate="2014-12-08" />
    <Contract ContractNumber="AD1004" ContractDate="2014-12-08" />
  </Client>
</Clients>

您可以使用上面的XML生成代码来生成所需的xml结构,包括OP中引用的其余类,并有效避免任何数据重复。

您最终可以使用Newtonsoft Json将XML序列化为Json。