lex*_*eme 2 c# design-patterns dependency-injection ninject repository
拥有一个通用的存储库
public class Repository<T>
where T: Entity<T>
{
/*anything else*/
}
Run Code Online (Sandbox Code Playgroud)
应该是每个聚合根的具体存储库
class ProductRepository : Repository<Product>
{
}
class CategoryRepository : Repository<Category>
{
}
Run Code Online (Sandbox Code Playgroud)
被创造?
另外,我如何使用DI(Ninject
)与存储库的通用实现.
样品是apreciated!
谢谢!
我在SO的问题中看到了很多滥用泛型的问题,虽然它并不一定会引用你的问题(虽然它有助于澄清),但我认为一旦在这里写了一个摘要.
泛型是typeless
对行为的重用(几乎,因为您可以使用限制来限制类型).如果所有类型(或限制为限制的行为)共享行为,则使用泛型.
但是,如果每个泛型类型的实现需要单独实现,那么使用泛型并没有帮助,而是简化为装饰 - 对我来说这是糟糕的设计.
好的,我们有一个例子:
interface IConverter<T1, T2>
{
T1 Convert(T2 t2);
}
Run Code Online (Sandbox Code Playgroud)
这看起来像一个很好的泛型(将一种类型转换为另一种类型),但我必须将所有这些类型的组合实现为不同的转换器.而且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
}
Run Code Online (Sandbox Code Playgroud)
注意
有些人认为存储库必须允许将标准传递到存储库(Eric Evans DDD书),但我再次认为我不必同意这一点.我更喜欢存储库中的域名重要声明(例如GetTopFiveBestSellingProducts
或者GetTopBestSellingProducts
),除非报告编写者中有100个这样的声明只占案例的1%.
第二个问题:
我不使用Ninject但是对于任何DI,这是你如何做到的
// PSEUDOCODE !!!
container.Register<IProductRepository , ProductRepository>();
Run Code Online (Sandbox Code Playgroud)
根据DI框架,它可能会略有不同.