选择性POCO属性

时间:2015-04-15 15:00:58

标签: c# web-services serialization poco dto

假设我有下面列出的用于通过Web服务将数据传递给客户端的类(简化了类):

public class Customer
{
    public int CustomerId { get; set; }
    public string Name { get; set; }
    public List<Sales> CustomerSales 
    {
        get { /*code to return list of customersales */ }
    }
    public double TotalSalesAmount 
    {
        get { /*code that return total sales amount for customer*/ }
    }
    public double AverageSalesPerMonth
    {
        get { /*code that return average sales amount per month for customer*/ }
    }
}

public class Sales
{
    public int SalesId { get; set; }
    public int CustomerId { get; set; }
    public DateTime SalesDate { get; set; }
    public double SalesAmount { get; set; }
}

我的问题是关于这两个属性:

    public double TotalSalesAmount 
    {
        get { /*code that return total sales amount for customer*/ }
    }
    public double AverageSalesPerMonth
    {
        get { /*code that return average sales amount per month for customer*/ }
    }

有时客户端只需要客户信息,即 CustomerId Name ,然后有时需要 CustomerId 名称 TotalSalesAmount 或其组合等。对此最好的做法是什么?我找到了一些关于这个主题的讨论,并提出了以下建议:

  • 为每个场景创建一个DTO(这意味着我将最终得到100个DTO,因为示例已经简化)
  • 根据需要为每个计算和执行方法创建一个单独的服务方法(这意味着将进行大量服务调用)
  • 将属性保留在上面的类中(这将意味着大量的开销 - 某些计算可能非常耗费资源 - 这不是必需的)。

我确信没有这方面的灵丹妙药,但想知道最好的方法是什么?

2 个答案:

答案 0 :(得分:1)

你能有一个方法,比如:

[Route("api/customers/{customerId:int}")]
public Customer GetCustomerInformation(int customerId, bool includeTotalSales, bool includeAverageSalesMonth)
{
    var customer = new Customer { CustomerId = customerId };
    customer.TotalSalesAmount = includeTotalSales ? CalculateTotalSales(customerId) : null;
    // etc
}

我认为您正在使用Web API 2,但您可以根据自己的使用情况进行更改。这样你就可以有一个DTO,一个服务调用,没有开销。这适用于您的申请吗?

编辑:来电者会调用类似http://url:port/api/customers/111111?includeTotalSales=true&includeAveragesSalesMonth=false的内容。

答案 1 :(得分:1)

我同意@Luu - 一般 - 但我使用enum而不是bool标志 - 比如:

public Customer GetCustomerInformation(int customerId, LevelOfDetail detail 
  = LevelOfDetail.All)
{
  var customer = new Customer { CustomerId = customerId };
  customer.TotalSalesAmount = detail.HasFlag(LevelOfDetail.TotalSalesAmount) ? CalculateTotalSales(customerId) : null;
  // etc
  return customer;
}

[Flags]
public enum LevelOfDetail : int
{
  TotalSalesAmount = (1 << 0),
  AverageSalesPerMonth = (1 << 1),
  All = TotalSalesAmount | AverageSalesPerMonth
}