Использование Ninject в архитектуре приложения SOLID - PullRequest
9 голосов
/ 03 августа 2011

Я начинаю с MVC3 и хочу использовать некоторую гибкую архитектуру, поэтому я прочитал десятки блогов, книгу (Pro ASP.NET MVC 3), прочитал о принципах SOLID и, наконец, получил структуру приложения, которая мне нравится(или, по крайней мере, пока так думаю, потому что я еще ничего на нем не построил):

enter image description here

В этой структуре:

  • Домен содержит классы POCO и определяет интерфейсы сервисов
  • Сервисы реализуют интерфейсы сервисов и определяют интерфейсы репозиториев
  • Данные реализуют интерфейсы репозиториев
  • WebUI и Домен используют Сервисы
  • Сервисы используют репозитории
  • WebUI, Сервисы и Данные зависят от домена для классов POCO

Основная причина использования Доменом Сервисов заключается в проверке уникальных ключей в методах проверки POCO (IValidatable) классы.

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

  1. I 'Я использую проект Data.Tests с модульными тестами для репозиториев, но не нашел способа внедрить (используя Ninject) реализацию службы (в конструкторе или иным образом) в модель, поэтому метод Validate может вызватьCheckUniqueKey на сервисе.

  2. Я не нашел никаких ссылок на подключение Ninject к проекту TEST (много для проекта WebUI).

Что яЯ пытаюсь достичь этого, будучи в состоянии переключиться с EF на что-то еще, например DAPPER, просто изменив сборку DATA.

ОБНОВЛЕНИЕ

Прямо сейчас (по состоянию на09 августа 2011 г.) Ninject работает, но мне кажется, что я что-то упустил.

У меня есть CustomerRepository с двумя конструкторами:

public class CustomerRepository : BaseRepository<Customer>, ICustomerRepository
{
    // The repository usually receives a DbContext
    public CustomerRepository(RefAppContext context)
        : base(context)
    {
    }

    // If we don't receive a DbContext then we create the repository with a defaulte one
    public CustomerRepository()
        : base(RefApp.DbContext())
    {
    }

    ...
}

В TestInitialize:

// These are for testing the Repository against a test database

[TestInitialize()]
public void TestInitialize()
{
    // Context used for tests
    this.context = new RefAppContext();

    // This is just to make sure Ninject is working, 
    // would have used: repository = new CustomerRepository(context);

    this.kernel = NinjectMVC3.CreateKernel();

    this.kernel.Rebind<ICustomerRepository>().To<CustomerRepository>().WithConstructorArgument("context", context);

    this.repository = kernel.Get<ICustomerRepository>();

}

В классе Customer:

public class Customer : IValidatableObject 
{
    ...

    public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
    {
        // I want to replace this with a "magic" call to ninject
        CustomerRepository rep = new CustomerRepository();

        Customer customer = rep.GetDupReferenceCustomer(this);

        if (customer != null)
            yield return new ValidationResult("Customer \"" + customer.Name + "\" has the same reference, can't duplicate", new [] { "Reference" });
    }

    ...
}

Какой лучший способ использовать Ninject в этом сценарии?

Любая помощь будет высоко оценена.

ОТВЕТ, ВЕРНУТЬСЯ

Я пока рассмотрю этот вопрос как ответ.Я мог бы заставить Ninject работать, вроде бы, но похоже, что для достижения Принципа инверсии зависимости (DIP) SOLID потребуется больше времени.

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

Спасибо всем.

1 Ответ

3 голосов
/ 03 августа 2011

Модульное тестирование должно проводиться без Ninject.Просто создайте экземпляр тестируемого объекта и вставьте макет для каждой зависимости вручную.

Для интеграционных тестов вы можете использовать ядро, включая все привязки из загрузчика приложения, и rebind все, что вы хотитезаменить на макет.Например, замените привязку Session тем, который использует хранилище данных в памяти вместо реальной базы данных.

...