选择性 POCO 属性
Selective POCO properties
假设我有下面列出的 类,用于通过 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、Name 和 TotalSalesAmount 或其组合等等。关于此的最佳做法是什么。我发现了一些关于这个主题的讨论,并提出了以下建议:
- 为每个场景创建一个 DTO(这意味着我最终会得到 100 个 DTO,因为示例已简化)
- 为每个计算创建一个单独的服务方法并根据需要执行方法(这意味着将进行大量服务调用)
- 如上保留 类 中的属性(这意味着大量开销 - 某些计算可能非常耗费资源 - 这不是必需的)
我确信没有灵丹妙药,但想知道最好的方法是什么?
你能不能有一个单一的方法,比如:
[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
.
我同意@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
}
假设我有下面列出的 类,用于通过 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、Name 和 TotalSalesAmount 或其组合等等。关于此的最佳做法是什么。我发现了一些关于这个主题的讨论,并提出了以下建议:
- 为每个场景创建一个 DTO(这意味着我最终会得到 100 个 DTO,因为示例已简化)
- 为每个计算创建一个单独的服务方法并根据需要执行方法(这意味着将进行大量服务调用)
- 如上保留 类 中的属性(这意味着大量开销 - 某些计算可能非常耗费资源 - 这不是必需的)
我确信没有灵丹妙药,但想知道最好的方法是什么?
你能不能有一个单一的方法,比如:
[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
.
我同意@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
}