【问题标题】:Selective POCO properties选择性 POCO 属性
【发布时间】:2015-06-21 14:57:45
【问题描述】:

假设我有下面列出的类,这些类用于通过 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*/ }
    }

有时客户只需要客户信息即CustomerIdName,而有时它需要CustomerId名称TotalSalesAmount 或其组合等等。这方面的最佳做法是什么。我发现了一些关于这个话题的讨论,并提出了以下建议:

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

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

【问题讨论】:

    标签: c# web-services serialization poco dto


    【解决方案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
    }
    

    【讨论】:

    • 出于好奇,为什么要移位?为什么不在枚举中简单地设置 TotalSalesAmount = 0 或 AverageSalesPerMonth = 1?也许我错了,但这似乎影响了可读性。
    • @JamesShaw - 这是一个品味问题。恕我直言,当你有很多它们时看起来更好(1
    • 这将是我的方案最干净和最好的解决方案。非常感谢!
    【解决方案2】:

    你能不能有一个方法,比如:

    [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&amp;includeAveragesSalesMonth=false

    【讨论】:

      猜你喜欢
      • 2011-08-23
      • 2012-09-08
      • 1970-01-01
      • 1970-01-01
      • 2010-10-19
      • 2010-10-10
      • 1970-01-01
      • 2012-04-20
      • 1970-01-01
      相关资源
      最近更新 更多