[英]C# Service Layer Design Pattern
我們正在研究創建一個新項目,並希望探索使用Repository和Service層模式,目的是創建松散耦合的代碼,使用模擬存儲庫完全可測試。
請參閱下面的基本架構構思。 我們將使用接口來描述存儲庫,並將這些接口注入服務層以刪除任何依賴項。 然后使用autofac我們將在運行時連接服務。
public interface IOrderRepository
{
IQueryable<Order> GetAll();
}
public class OrderRepository : IOrderRepository
{
public IQueryable<Order> GetAll()
{
return new List<Order>().AsQueryable();
}
}
public class OrderService
{
private readonly IOrderRepository _orderRepository;
public OrderService(IOrderRepository orderRepository)
{
_orderRepository = orderRepository;
}
public IQueryable<Order> GetAll()
{
return _orderRepository.GetAll();
}
}
public class EmailService
{
public void SendEmails()
{
// How do I call the GetAll method from the order serivce
// I need to inject into the orderService the repository to use
}
}
我們在找到最佳前進方法時遇到了一些問題。
1)服務是否應該再現CRUD方法,因為看起來我們可能正在復制代碼而沒有真正的好處。 或者UI應該直接調用存儲庫嗎?
2)當服務需要調用另一個服務時會發生什么。 在上面的示例中,如果電子郵件服務需要獲取所有訂單,我們是否將訂單服務注入電子郵件服務?
希望這是有道理的
電子郵件服務不應該知道OrderService之類的服務,你需要Mediator使用Email && Order服務以便它們被解耦,或者適配器以使IOrder
適應IEmail
:
IEnumerable<IOrder> orders = orderService.GetAll();
// TODO: Create emails from orders by using OrderToEmailAdaptor
IEnumerable<IEmail> emails = ...
emailService.SendEmails(emails);
public sealed class EmailService
{
public void SendEmails(IEnumerable<IEmail> emails)
{
}
}
調解員 :
定義一個封裝一組對象如何交互的對象。 Mediator通過使對象明確地相互引用來促進松散耦合,並且它允許您獨立地改變它們的交互
適配器 :
適配器模式(通常稱為包裝器模式或簡稱包裝器)是一種設計模式,它將類的一個接口轉換為兼容接口
看一下Domain Driven Design。 DDD將大部分邏輯移動到實體( Order
, Email
)中,並讓他們使用存儲庫。
1)服務是否應該再現CRUD方法,因為看起來我們可能正在復制代碼而沒有真正的好處。 或者UI應該直接調用存儲庫嗎?
當您發現自己在實體外部編寫業務邏輯時,將使用DDD中的服務。
2)當服務需要調用另一個服務時會發生什么。 在上面的示例中,如果電子郵件服務需要獲取所有訂單,我們是否將訂單服務注入電子郵件服務?
在構造函數中注入它。 但是,訂單服務應該發送電子郵件,而不是相反。
DDD方法是創建一個OrderNotificationService
,它接受域事件OrderCreated
並編寫一個通過EmailService
發送的EmailService
更新
你誤解了我。 重復邏輯永遠不會好。 當我的存儲庫有一個方法時,我不會在名為GetAll
服務中放置一個方法。 我也不會把這個方法放在我的實體中。
示例代碼:
var order = repository.Create(userId);
order.Add(articleId, 2);
order.Save(); // uses the repository
Order.Send()
應該創建OrderNotificationService
可以捕獲的域事件。
UPDATE2
Repository.Create
只是一個工廠方法(谷歌factory method pattern
),可以在一個地方獲得所有域模型創建。 它在db中沒有做任何事情(雖然它可能在將來的版本中)。
至於order.Save它將使用存儲庫來保存所有訂單行,訂單本身或其他任何需要的訂單。
您可以使用適配器模式或使用DI工具
public class EmailService
{
private IOrderRepository _orderservice = null;
public EmailService(IOrderService orderservice)
{
_orderservice = orderservice;
}
public void SendEmails()
{
_orderService.GetAll();
}
}
我要做的是
不直接從UI調用存儲庫,而是調用服務而服務應該使用存儲庫,
我會從電子郵件服務中調用Order存儲庫的方法,這樣我只會將OrderRepository注入電子郵件服務(而不是訂購服務)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.