簡體   English   中英

C#服務層設計模式

[英]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將大部分邏輯移動到實體( OrderEmail )中,並讓他們使用存儲庫。

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();
    }
}

我要做的是

  1. 不直接從UI調用存儲庫,而是調用服務而服務應該使用存儲庫,

  2. 我會從電子郵件服務中調用Order存儲庫的方法,這樣我只會將OrderRepository注入電子郵件服務(而不是訂購服務)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM