我有一个反复出现的模式,我在一些必须生成的报告中看到。这些报告是基于日期范围的报告,需要按不同级别汇总。
为简单起见,我们假设此报告在叶节点级别(最低级别)生成标题和配额。在订单项级别(这是各种叶节点的集合),我想聚合配额并提供单独的标题。这些订单项将进一步累积到另一个级别,这将再次聚合配额并具有唯一标题。
所以报告会是这样的:
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 LineItem : IInventoryReportItem
我也可以像这样构建一个集合:
public class LineItems : IList<IInventoryReportItem>, IInventoryReportItem
{
private readonly List<IInventoryReportItem> _subLineItems;
public LineItems()
{
_subLineItems = new List<IInventoryReportItem>();
}
我的报告就是这样:
public class InventoryReport
{
public DateRange DateRange { get; set; }
public LineItems LineItems { get; set; }
}
我现在可以轻松地以分层方式构建报告,但我仍然需要从外部调用聚合函数,而不是为我自动计算:
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});
我是否仍然可以灵活地添加单个订单项或一系列商品,还可以使用合并自动计算/汇总数据?
任何帮助都会很棒!
谢谢你, 阿努普
答案 0 :(得分:0)
对我而言,您似乎正在寻找RX(反应性扩展),因此您不必每次都在每个级别手动求和。相反,只需设置必要的订阅并自动重新计算。例如: Good example of Reactive Extensions Use
答案 1 :(得分:0)
我解决了这个问题。对于那些感兴趣的人,我的解决方法如下:
我构建了一个界面,如下所示:
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; }
}
我还创建了一个名为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>();
}
}
所有聚合都在此集合类级别完成。
报告类如下:
public class InventoryReport
{
public DateRange DateRange { get; set; }
public IInventoryReportItem LineItems { get; set; }
}
然后我就能像这样构建报告:
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"};
我从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
}
}
使用这种方法,我能够消除执行聚合的开销,并且仍然能够使用相同签名的集合或单个项目。
希望有人觉得这很有用!