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

本文关键字:嵌套 对象 结构 提取 平面 列表 | 更新日期: 2023-09-27 18:33:30

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

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 文件,而不会重复。

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

表示嵌套对象结构的另一种方法是使用 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。

我不知道

有什么方法可以从另一个类自动提取一个类。您可以尝试添加提取所需信息的扩展方法,例如:

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 自动执行此操作的方法有更好的主意。