首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >尼尼姆工厂管理

尼尼姆工厂管理
EN

Stack Overflow用户
提问于 2014-10-14 17:37:55
回答 1查看 75关注 0票数 0

我使用Ninject.Extensions.Factory来控制存储库层的生命周期。我希望有一个单一的参照点,从中我可以获得对所有存储库的引用,并让它们懒惰地可用。Ninject Factory方法似乎是一个很好的解决方案,但我对我的解决方案不太确定:

代码语言:javascript
复制
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类。

代码语言:javascript
复制
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参数的数量,比如传递一个接口的数组/字典或类似的东西?

我已经考虑过在这个场景中使用属性注入,但大多数文章建议在一般情况下避免使用属性注入。

是否有一种更普遍的模式可以使这更容易管理?

一般来说,这是一个好办法吗?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2014-10-15 05:14:49

使用类似这样的存储库接口已成为相当普遍的做法

代码语言:javascript
复制
public interface IRepository
{
    T LoadById<T>(Guid id);

    void Save<T>(T entity);

    ....
}

而不是像IContentRepositoryICategoryRepository这样的大量特定存储库。

只有在实体类型和操作具有特定逻辑的情况下,特定的存储库才会有用,例如,验证它是否有效。但是这样的操作是一个“方面”,或者是一个直接的关注点,你应该这样做。对保存进行管理/执行验证不应该实现x次,而应该只执行一次。唯一需要具体实现的是确切的验证规则(干的)。但是,这些应该在单独的类中实现,并由组合使用,而不是继承。

此外,对于“基于用例”检索实体或多个实体的内容,您应该使用特定的查询类,而不是将方法放在存储库接口(SRPSOC)上。GetProductsByOrder(Guid orderId)就是一个例子。这既不应该出现在产品上,也不应该出现在上,而应该放在单独的类中。

更进一步,使用工厂延迟创建所有存储库似乎不是一个好主意。为什么?

  • 使软件变得更复杂(因此更难维护和扩展)
  • 通常可以忽略不计的性能增益
  • 劣化可测性
  • 还请参阅Mark的博客文章服务定位器是一种反模式,他在文章中还谈到了后期创建与整个对象图的组合的缺点。
  • 我并不是说你永远不应该使用工厂/懒惰,而是只有当你有了一个很好的理由:)

查询示例

我对EntityFramework不太熟悉。我更了解NHibernate,所以你看。

代码语言:javascript
复制
public class GetParentCategoriesQuery : IGetParentCategoriesQuery
{
    private readonly EntityFrameworkContext context;

    public GetParentCategories(EntityFrameworkContext context)
    {
        this.context = context;
    }

    public IEnumerable<Category> GetParents(Category child)
    {
        return this.context.Categories.Where(x => x.Children.Contains(child));
    }
}

因此,基本上唯一的改变是将GetParentCategoriesQuery提取到它自己的类中。DbContext实例必须与其他查询和存储库实例共享。对于web项目,这是通过绑定DbContext .InRequestScope()来完成的。对于其他应用程序,您可能需要使用另一种机制。

查询的使用非常简单:

代码语言:javascript
复制
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...
   }
}

范围划分的一个替代方法是让存储库实例化查询类型并将DbContext传递给查询实例(这可以使用工厂扩展来完成):

代码语言:javascript
复制
public TQuery CreateQuery<TQuery>()
{
    return this.queryFactory.Create<TQuery>(this.context);
}

可用于如下用途:

代码语言:javascript
复制
IEnumerable<Category> parents = repository
    .CreateQuery<GetParentCategoriesQuery>()
    .GetParents(someCategory);

但请注意,此替代方案将再次延迟创建查询,从而导致测试性降低(绑定问题可能会在更长时间内未被检测到)。

GetParentCategoriesQuery是存储库层的一部分,但不是存储库类的一部分。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/26366871

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档