Dependency injection 工厂管理
我使用Ninject.Extensions.Factory来控制存储库层的生命周期。我希望有一个单一的参考点,从中我可以获得对所有存储库的参考,并使它们可以懒洋洋地使用。Ninject工厂方法似乎是一个很好的解决方案,但我不太确定我的解决方案:Dependency injection 工厂管理,dependency-injection,ninject,inversion-of-control,Dependency Injection,Ninject,Inversion Of Control,我使用Ninject.Extensions.Factory来控制存储库层的生命周期。我希望有一个单一的参考点,从中我可以获得对所有存储库的参考,并使它们可以懒洋洋地使用。Ninject工厂方法似乎是一个很好的解决方案,但我不太确定我的解决方案: public class PublicUow : IPublicUow { private readonly IPublicRepositoriesFactory _publicRepositoriesFactory; public P
public class PublicUow : IPublicUow
{
private readonly IPublicRepositoriesFactory _publicRepositoriesFactory;
public PublicUow(IPublicRepositoriesFactory publicRepositoriesFactory)
{
_publicRepositoriesFactory = publicRepositoriesFactory;
}
public IContentRepository ContentRepository { get { return _publicRepositoriesFactory.ContentRepository; } }
public ICategoryRepository CategoryRepository { get { return publicRepositoriesFactory.CategoryRepository; } }
}
问题在于PublicRepositories类
public class PublicRepositoriesFactory : IPublicRepositoriesFactory
{
private readonly IContentRepositoryFactory _contentRepositoryFactory;
private readonly ICategoryRepositoryFactory _categoryRepositoryFactory;
public PublicRepositoriesFactory(IContentRepositoryFactory contentRepositoryFactory, ICategoryRepositoryFactory categoryRepositoryFactory)
{
_contentRepositoryFactory = contentRepositoryFactory;
_categoryRepositoryFactory = categoryRepositoryFactory;
}
public IContentRepository ContentRepository { get { return _contentRepositoryFactory.CreateContentRepository(); } }
public ICategoryRepository CategoryRepository { get { return _categoryRepositoryFactory.CreateCategoryRepository(); } }
}
我担心随着存储库数量的增加,这将变得难以管理,这个类在当前实现中可能需要大约20-30个构造函数参数。
有没有一种方法可以减少ctr参数的数量,比如传递接口数组/字典或类似的东西
我曾经考虑过在这个场景中使用属性注入,但大多数文章建议一般避免使用属性注入
是否有一种更通用的模式可以让这更容易管理
这通常是一种好方法吗?使用存储库接口(如
public interface IRepository
{
T LoadById<T>(Guid id);
void Save<T>(T entity);
....
}
因此,基本上您所做的唯一更改就是将GetParentCategoriesQuery
提取到它自己的类中。DbContext实例必须与其他查询和存储库实例共享。对于web项目,这是通过绑定DbContext
.InRequestScope()
完成的。对于其他应用,您可能需要使用另一种机制
查询的用法非常简单:
public class CategoryController
{
private readonly IRepository repository;
private readonly IGetParentCategoriesQuery getParentCategoriesQuery;
public CategoryController(
IRepository repository,
IGetParentCategoriesQuery getParentCategoriesQuery)
{
this.repository = repository;
this.getParentCategoriesQuery = getParentCategoriesQuery;
}
public void Process(Guid categoryId)
{
Category category = this.repository.LoadById(categoryId);
IEnumerable<Category> parentCategories =
this.getParentCategoriesQuery(category);
// so some stuff...
}
}
其使用方式如下:
IEnumerable<Category> parents = repository
.CreateQuery<GetParentCategoriesQuery>()
.GetParents(someCategory);
IEnumerable parents=存储库
.CreateQuery()
.GetParents(someCategory);
但是请注意,这种替代方法只会延迟创建查询,从而导致可测试性降低(绑定问题可能在更长时间内未被检测到)
GetParentCategoriesQuery
是存储库层的一部分,但不是存储库类的一部分。在我的例子中,每个存储库都是IRepository的超集,它扩展了一个基类,因此提供了所有通用功能。上面提到过,我还没有遇到一个真实世界的应用程序,在这个应用程序中,每个域实体都没有特定的逻辑。例如,GetParentCategories和GetRecentContents是两个完全不同的实现,不能与简单的IRepository一起使用。另外,如果我错了,请纠正我的错误(在这方面还是新手),但在我当前的实现中,没有服务定位器反模式,因为我从未在组合根之外引用IOC容器?像GetParentCategories
和GetRecentContents
这样的方法不属于存储库(SOC、SRP),intead每个类都应该放在一个单独的类中,比如GetParentCategoriesQuery
。这样做之后,您将看到每个存储库类现在只继承基类,而不再做其他任何事情……至于服务定位器反模式:在Mark Seeman引用的文章中,他描述了为什么不延迟/延迟实例化类型是有益的。争论更多的是关于可测试性和对象树更易于理解/维护,而不是关于服务位置。顺便说一句,自动生成的工厂本身引用了容器,并且正在使用服务位置?在需要父类别的地方,我需要实例化一个新对象,并通过构造函数注入提供依赖关系?您是否可以修改您的答案并添加一些代码,以澄清所述类与存储库层的交互,并显示一个简单的用例?好的,我已经这样做了。在SO中也有其他帖子介绍了这一点,但我很惊讶google搜索结果中出现了很多设计糟糕的例子,其中一些是微软自己的。
public TQuery CreateQuery<TQuery>()
{
return this.queryFactory.Create<TQuery>(this.context);
}
IEnumerable<Category> parents = repository
.CreateQuery<GetParentCategoriesQuery>()
.GetParents(someCategory);