2015-04-15 2 views
2

Допустим, у меня есть классы, перечисленные ниже, которые используются для передачи данных клиента через веб-сервис (классы упрощены):Selective POCO свойства

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 и Имя, а затем иногда это потребует логотипо rId, Наименование и TotalSalesAmount или их комбинация и так далее. Какая была бы лучшая практика в этом отношении. Я обнаружил, было сделано несколько дискуссий по данной теме, а также следующие предложения:

  • Создание DTO для каждого сценария (это означало бы, что я в конечном итоге с 100 в DTO это как пример упрощенной)
  • Создать отдельный метод обслуживания для каждого метода вычислений и выполнения при необходимости (это будет означать, что будет сделано множество вызовов услуг)
  • Оставьте свойства в классах, как указано выше (это будет означать много накладных расходов - некоторые вычисления могут быть очень ресурсоемкие - это не требуется)

Я уверен, что для этого нет серебряной пули, но хотелось бы знать, какой будет лучший подход?

ответ

1

Я согласен с @Luu - в целом - но я хотел бы использовать перечисление вместо 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 
} 
+0

из любопытства, почему немного сместить? Почему бы просто не задать TotalSalesAmount = 0 или AverageSalesPerMonth = 1 в вашем перечислении? Возможно, я ошибаюсь, но, похоже, это отвлекает от читаемости. –

+1

@JamesShaw - это вопрос вкуса. ИМХО это выглядит лучше, когда у вас их много (1 << 17) является более читаемым, чем 131072. –

+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.