2013-12-15 7 views
0

Мне бы хотелось, чтобы на моем уровне MVC не было репозиториев вообще.Как использовать простой инжектор для репозитория в бизнес-слое

У меня есть общий EFRepository, IRepository и PASContext (который наследуется от DbContext) в моем слое проекта DAL.

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

Но в моем решении у меня также есть проект BLL, и я хочу, чтобы слой MVC говорил только со слоем BLL, так как это архитектура проекта, и в будущем я бы хотел добавить логику в классы в слое BLL.

Также я не хочу, чтобы создать контекст, в моем BLL слое, но Repository не имеет конструктора, который принимает 0 аргументов, это мой ProductBLL класс:

public class BLLProducts 
{ 
    IRepository<Product> ProductRepository; 

    public BLLProducts(EFRepository<Product> Repository) 
    { 
     ProductRepository = Repository; 
    } 

    public ICollection<Product> getAll() 
    { 
     return ProductRepository.All().ToList(); 
    } 
} 

Как я могу инициировать BLLProduct класс от контроллера или из unitTest без создания репозитория/контекста? поэтому я могу сохранить свою абстракцию здесь.

Я знаю, что мне нужно как-то использовать простой инжектор, я просто не знаю, как это сделать.

ответ

1

С точки зрения контроллера, это просто вопрос инъекции BLLProducts в него, как это:

// constructor 
public HomeController(BLLProducts products) { 
    this.products = products; 
} 

С точки зрения модульного тестирования, позволяя контроллеры зависят от конкретных классов неоптимальным (это нарушает Dependency Inversion Principle). Это не оптимально, так как теперь вам нужно создать экземпляр BLLProducts и создать его с помощью DbContext, но этот DbContext специфичен для Entity Framework, который зависит от базы данных. Это делает тестирование сложнее и медленнее. Вы хотите, чтобы ваши модульные тесты выполнялись без базы данных.

Таким образом, решение этого заключается в том, чтобы скрыть этот класс BLLProducts за абстракцией. Простым способом сделать это является извлечение интерфейса из этого класса:

public interface IBLLProducts { 
    ICollection<Product> getAll(); 
} 

Это значительно упрощает модульность тестирования контроллеров. Единственное, что вам нужно сделать, это пусть это зависит от этого нового интерфейса:

public HomeController(IBLLProducts products) { 
    this.products = products; 
} 

Вам нужно будет зарегистрировать этот IBLLProducts интерфейс в простом Injector:

container.Register<IBBLProducts, BLLProducts>(); 

Вся эта модель все еще имеет некоторые недостатки в Это. Например, хотя Simple Injector может создавать и удалять DbContext для вас, где вы называете SubmitChanges? Выполнение этого при завершении веб-запросов - довольно плохая идея. Единственное удобное решение, которое я нашел для этого, - это перейти к более SOLID-архитектуре. Например, взгляните на this question.

+0

Спасибо большое! какую SOLID-архитектуру вы бы мне порекомендовали, что близко к моей нынешней архитектуре? ('BLL' разговаривает с' DAL' через репозитории, а 'MVC' разговаривает с' BLL', используя простой инжектор) – jony89

+0

@ jony89: Изучите 5 принципов SOLID. Они дают вам гораздо более важное руководство, чем различные архитектурные стили, такие как трехуровневая архитектура.Программа для абстракций, ограничение обязанностей классов и предотвращение необходимости изменять классы при добавлении функций. – Steven