Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
分层数据-复合模式C#_C#_Design Patterns - Fatal编程技术网

分层数据-复合模式C#

分层数据-复合模式C#,c#,design-patterns,C#,Design Patterns,我在我必须生成的一些报告中看到了一种循环模式。这些报告是基于日期范围的报告,需要按不同级别进行汇总 为了简单起见,假设此报告在叶节点级别(最低级别)生成标题和配额。在行项目级别(它是各种叶节点的集合),我希望聚合配额并提供一个单独的标题。这些行项目将进一步上卷到另一个级别,该级别将再次汇总配额并具有唯一的标题 所以报告应该是这样的: ROOT LEVEL | Title = "Main Report" | Quota = 100 Month Level | Title = "Jan"

我在我必须生成的一些报告中看到了一种循环模式。这些报告是基于日期范围的报告,需要按不同级别进行汇总

为了简单起见,假设此报告在叶节点级别(最低级别)生成标题和配额。在行项目级别(它是各种叶节点的集合),我希望聚合配额并提供一个单独的标题。这些行项目将进一步上卷到另一个级别,该级别将再次汇总配额并具有唯一的标题

所以报告应该是这样的:

ROOT LEVEL | Title = "Main Report" | Quota = 100
   Month Level    | Title = "Jan" | Quota = 100
     Week Level   | Title = "Week 1" | Quota = 25
     Week Level   | Title = "Week 2" | Quota = 75
我有没有办法使用复合模式来构建它?我尝试过许多方法。大多数都不够,因为我无法有效地将配额汇总到更高的级别

我可以构建这样的界面:

public interface IInventoryReportItem
{ 
    string Title { get; set; }
    int Quota { get; set; }
}
public class InventoryReport
{
    public DateRange DateRange { get; set; }
    public LineItems LineItems { get; set; }

}
然后我可以构建一个行项目,如下所示:

public class LineItem : IInventoryReportItem
我还可以建立这样的集合:

 public class LineItems : IList<IInventoryReportItem>, IInventoryReportItem
{
    private readonly List<IInventoryReportItem> _subLineItems;

    public LineItems()
    {
        _subLineItems = new List<IInventoryReportItem>();
    }
我现在可以以分层方式轻松构建报告,但我仍然需要从外部调用聚合函数,而不是由它自动计算:

var report = new InventoryReport();

        var week1Days = new LineItems
        {
            new LineItem {Quota = 20, Title = "Day 1"},
            new LineItem {Quota = 10, Title = "Day 2"}
        };

        var week2Days = new LineItems
        {
            new LineItem {Quota = 10, Title = "Day 1"},
            new LineItem {Quota = 10, Title = "Day 2"}
        };

        var week1 = new LineItems {week1Days};
        week1.Quota = week1.Sum(x => x.Quota);
        week1.Title = "Week1";


        var week2 = new LineItems {week2Days};
        week2.Quota = week2.Sum(x => x.Quota);
        week2.Title = "Week2";

        var month1 = new LineItems(new List<IInventoryReportItem> {week1, week2});
        month1.Title = "January";
        month1.Quota = month1.Sum(x => x.Quota);

        report.LineItems = new LineItems(new List<IInventoryReportItem> {month1});
var report=newinventoryreport();
var week1Days=新的行项目
{
新的行项目{Quota=20,Title=“第1天”},
新的行项目{Quota=10,Title=“第2天”}
};
var week2Days=新的行项目
{
新的行项目{Quota=10,Title=“第1天”},
新的行项目{Quota=10,Title=“第2天”}
};
var week1=新的行项目{week1Days};
week1.Quota=week1.Sum(x=>x.Quota);
week1.Title=“week1”;
var week2=新的行项目{week2ds};
周2.Quota=周2.Sum(x=>x.Quota);
week2.Title=“week2”;
var month1=新的行项目(新列表{week1,week2});
每月1.Title=“一月”;
month1.Quota=month1.Sum(x=>x.Quota);
report.LineItems=新的LineItems(新列表{month1});
有没有一种方法可以让我仍然可以灵活地添加一个行项目或一系列项目,并且还可以使用composite为我自动计算/聚合数据

任何帮助都会很好

谢谢,,
Anup

对我来说,似乎您正在寻找RX(反应式扩展),因此您不必每次在每个级别手动求和。相反,只需设置必要的订阅并自动重新计算即可。例如:
我解决了这个问题。对于那些感兴趣的人,我是这样解决的:

我构建了一个界面,如图所示:

public interface IInventoryReportItem
{
    string Title { get; set; }
    int Quota { get; }
    int TotalTicketsSold { get; }
    int TotalUnitsSold { get; }
    decimal TotalSalesAmount { get; }
}
我在一个名为LineItem的类中实现了此接口,如下所示:

public class LineItem : IInventoryReportItem
{

    public LineItem(string title, int quota, int totalTicketsSold, int totalUnitsSold, int totalCheckedIn,
        decimal totalSalesAmount)
    {
        Title = title;
        Quota = quota;
        TotalUnitsSold = totalUnitsSold;
        TotalTicketsSold = totalTicketsSold;
        TotalCheckedIn = totalCheckedIn;
        TotalSalesAmount = totalSalesAmount;
    }

    public string Title { get; set; }
    public int Quota { get; }
    public int TotalTicketsSold { get; }
    public int TotalUnitsSold { get; }
    public int TotalCheckedIn { get; }
    public decimal TotalSalesAmount { get; }

}
public class InventoryReport
{
    public DateRange DateRange { get; set; }
    public IInventoryReportItem LineItems { get; set; }

}
我还创建了一个名为LineItems的自定义集合类,如图所示。请注意,集合的类型为IInventoryReportItem本身:

public class LineItems : IInventoryReportItem
{
    public string Title { get; set; }
    public int Quota => Contents?.Sum(x => x.Quota) ?? 0;
    public int TotalTicketsSold => Contents?.Sum(x => x.TotalTicketsSold) ?? 0;
    public int TotalUnitsSold => Contents?.Sum(x => x.TotalUnitsSold) ?? 0;
    public decimal TotalSalesAmount => Contents?.Sum(x => x.TotalSalesAmount) ?? 0;

    public readonly List<IInventoryReportItem> Contents;

    public LineItems(List<IInventoryReportItem> lineItems)
    {
        Contents = lineItems ?? new List<IInventoryReportItem>();
    }

}
然后,我可以这样构建报告:

 Report = new InventoryReport();
        var week1 = new LineItems(new List<IInventoryReportItem>
        {
            new LineItem("Day1", 10, 10, 10, 4, 100),
            new LineItem("Day2", 10, 5, 5, 1, 50)
        })
        {Title = "Week1"};

        var week2 = new LineItems(new List<IInventoryReportItem>
        {
            new LineItem("Day1", 20, 20, 20, 20, 200),
            new LineItem("Day2", 20, 5, 5, 5, 50)
        }) {Title = "Week2"};

        var month1 = new LineItems(new List<IInventoryReportItem> {week1, week2}) {Title = "January"};
        Report.LineItems = new LineItems(new List<IInventoryReportItem> {month1}) {Title = "Daily Report"};
使用这种方法,我能够消除执行聚合的开销,并且仍然能够使用使用相同签名的集合或单个项


希望有人觉得这很有帮助

LineItems
Quota
属性实现一个getter,该属性检查其自身的长度,如果大于0,则对其子项的
Quota
求和。我不确定这是否适合“复合模式”,但我不会让模式妨碍代码的工作。这是一个api的背后,我希望将其作为JSON发送。
{
"lineItems": {
"contents": [
  {
    "contents": [
      {
        "contents": [
          {
            "title": "Day1",
            "quota": 10,
            "totalTicketsSold": 10,
            "totalUnitsSold": 10,
            "totalCheckedIn": 4,
            "totalSalesAmount": 100
          },
          {
            "title": "Day2",
            "quota": 10,
            "totalTicketsSold": 5,
            "totalUnitsSold": 5,
            "totalCheckedIn": 1,
            "totalSalesAmount": 50
          }
        ],
        "title": "Week1",
        "quota": 20,
        "totalTicketsSold": 15,
        "totalUnitsSold": 15,
        "totalSalesAmount": 150
      },
      {
        "contents": [
          {
            "title": "Day1",
            "quota": 20,
            "totalTicketsSold": 20,
            "totalUnitsSold": 20,
            "totalCheckedIn": 20,
            "totalSalesAmount": 200
          },
          {
            "title": "Day2",
            "quota": 20,
            "totalTicketsSold": 5,
            "totalUnitsSold": 5,
            "totalCheckedIn": 5,
            "totalSalesAmount": 50
          }
        ],
        "title": "Week2",
        "quota": 40,
        "totalTicketsSold": 25,
        "totalUnitsSold": 25,
        "totalSalesAmount": 250
      }
    ],
    "title": "January",
    "quota": 60,
    "totalTicketsSold": 40,
    "totalUnitsSold": 40,
    "totalSalesAmount": 400
  }
],
"title": "Daily Report",
"quota": 60,
"totalTicketsSold": 40,
"totalUnitsSold": 40,
"totalSalesAmount": 400
  }
}