拥有像
这样的通用存储库public class Repository<T>
where T: Entity<T>
{
/*anything else*/
}
应该是每个聚合根的具体存储库,如
class ProductRepository : Repository<Product>
{
}
class CategoryRepository : Repository<Category>
{
}
被创造?
另外,我如何使用DI(Ninject
)与存储库的通用实现。
样品是apreciated!
谢谢!
答案 0 :(得分:5)
我在SO中的问题中看到了很多滥用泛型的问题,虽然它并不一定会引用你的问题(虽然这有助于澄清),但我认为一旦在这里写了一个摘要。
泛型是typeless
重用行为(几乎,因为你可以使用限制来限制类型)。如果所有类型(或限制为限制的行为)共享行为,则使用泛型。
但是,如果每个泛型类型的实现需要单独实现,那么使用泛型并没有帮助,而是简化为装饰 - 对我来说这是糟糕的设计。
好的,我们举个例子:
interface IConverter<T1, T2>
{
T1 Convert(T2 t2);
}
这看起来像一个很好的泛型(将一种类型转换为另一种类型),但我必须将所有类型的类型组合实现为不同的转换器。而IConverter<Apple, Orange>
没有任何意义。因此,这里的仿制药具有误导性和不好意思。
现在回到存储库。关于这个特定问题有很多文章(很多争议),但这是个人我的看法:
通常不建议使用通用存储库。 但是,根据我的个人经验,我使用通用存储库来实现常见的东西(由基础仓库实现),如果还有其他的话,则使用个别的:
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
}
注意强>
有些人认为存储库必须允许将标准传递到存储库(Eric Evans DDD book),但我再次认为我不必同意这一点。我更喜欢存储库中的域名重要声明(例如GetTopFiveBestSellingProducts
或GetTopBestSellingProducts
),除非报告编写者中有100个这样的声明只占案例的1%。
第二个问题:
我不使用Ninject但是对于任何DI,这是你如何做的
// PSEUDOCODE !!!
container.Register<IProductRepository , ProductRepository>();
取决于DI框架,它可能会略有不同。