Общий репозиторий, DI, Агрегационные корни - PullRequest
2 голосов
/ 04 января 2012

Имеет общий репозиторий, такой как

public class Repository<T> 
    where T: Entity<T> 
{ 
    /*anything else*/ 
}

должны конкретные хранилища на корень агрегации, такие как

class ProductRepository : Repository<Product> 
{
} 

class CategoryRepository : Repository<Category> 
{ 
}

быть создан?

Также, как мне использовать DI (Ninject) с общей реализацией репозитория.

Образцы оценены!

Спасибо!

1 Ответ

5 голосов
/ 04 января 2012

Я вижу много неправильного использования обобщений в вопросах в SO, и хотя это не обязательно относится к вашему вопросу (хотя это поможет прояснить), я думаю, что раз и навсегда напишите резюме здесь.

Generics - это typeless повторное использование поведения (почти, так как вы можете ограничить типы, используя ограничения).Если поведение является общим для всех типов (или для тех, которые ограничены ограничениями), вы используете универсальные шаблоны.

Однако если реализация каждого универсального типа требует индивидуальной реализации, использование универсальных шаблонов не помогает и сводится коформление - и для меня это плохой дизайн.

Хорошо, давайте приведем пример:

interface IConverter<T1, T2>
{
    T1 Convert(T2 t2);
}

Это похоже на хорошие генерики (преобразование одного типа в другой), но я долженреализовать все такие комбинации типов как разные конвертеры.И IConverter<Apple, Orange> не имеет никакого смысла.Следовательно, дженерики здесь вводят в заблуждение и ПЛОХО.

Теперь вернемся к репозиториям.Есть 100 статей по этому конкретному вопросу (много споров), но это личный мой взгляд:

Обычно не рекомендуется использовать универсальные репозитории. Однако , по своему личному опыту я использую общий репозиторий для реализации общих вещей (реализуемых базовым репо), а затем использую отдельные, если есть какие-либо дополнительные:

interface IRepository<T>
{
    T GetById(int id);
    IEnumerable<T> GetAll();
    void Save(T t);
}

class BaseRepository<T> : IRepository<T>
{
   ... // implement common methods
}

interface IProductRepository : IRepository<T>
{
    IEnumerable<T> GetTop5BestSellingProducts();    
}

class ProductRepository : BaseRepository<T>, IProductRepository 
{
    ... // implement important methods
}

ПРИМЕЧАНИЕ

Некоторые считают, что хранилище должно позволять передавать критерии в хранилище ( Книга Эрика Эванса DDD ), но я снова не чувствую, что должен согласиться с этим.Я предпочитаю доменно-значимое объявление в хранилище (например, GetTopFiveBestSellingProducts или GetTopBestSellingProducts), если в составителе отчетов нет сотен таких, как в 1% случаев.


Второй вопрос:

Я не использую Ninject, но для любого DI, вот как вы это делаете

 // PSEUDOCODE !!!
 container.Register<IProductRepository , ProductRepository>(); 

, в зависимости от структуры DI, она может немного отличаться.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...