MEF和实例创建的动态决策

时间:2011-10-11 11:18:35

标签: dependency-injection repository mef unit-of-work

这可能是一个奇怪的情况,但我希望在使用MEF获取导出时有时会重复使用相同的实例,有时会创建一个新的。

基本上我有一个WCF服务类是每次调用的实例。每个实例都导入一个RepositoryFactory,它也是每个服务类的新实例。我在Factory中返回一个Repository,一个存储库获取了一个IDbContext注入。

我希望Factory的每个实例都注入相同的IDbContext实例,但在Factory实例之间有单独的实例。

所以:

1) Factory1 is created
2) Factory1 creates Repository1-1 that gets IDbContext1 injected
3) Factory1 creates Repository1-2 that gets IDbContext1 injected
4) Factory2 is created
5) Factory2 creates Repository2-1 that gets IDbContext2 injected
6) Factory2 creates Repository2-2 that gets IDbContext2 injected

这应确保从同一工厂创建的存储库共享一个工作单元。

但是对MEF不熟悉我不知道我会怎么做。


修改

这就是我得到的:

public class RepositoryFactory
{
    private readonly CompositionContainer _container;

    [Import(RequiredCreationPolicy=CreationPolicy.NonShared)]
    private readonly IDbContext _context;

    public IRepository<T> CreateRepository<T>() where T : class, IEntity
    {
        //Somehow add the _context instance into the Repository import

        return _container.GetExportedValue<EntityRepository<T>>();
    }
}

然后

public class EntityRepository<T> : IRepository<T> where T : class, IEntity
{
    // Perhaps a contract name might help!!
    [Import(RequiredCreationPolicy=CreationPolicy.Shared)]
    protected readonly IDbContext _context;

2 个答案:

答案 0 :(得分:1)

用MEF无法做到这一点;无论你做什么,MEF容器都不能正确地作为你的工作单位管理员,它就不是为此做的。

您应该尝试显式编写工作单元基础结构,供DAL使用。您的存储库应明确要求工作单元管理器提供当前的工作单元及其适当的上下文。

看看NCommon https://github.com/riteshrao/ncommon中的代码;您可以重构工作单元功能以满足您的需求。

答案 1 :(得分:0)

好的,这是我想出的一个解决方案,但还没试过。它有点简单,实际上围绕MEF工作,但并没有真正打破它,至少在我的情况下不是这样。

向IRepository类添加以下方法:

void SetContext(IDbContext context);

或更好

IDbContext context { set; }

在工厂里:

public class RepositoryFactory
{
    private readonly CompositionContainer _container;

    [Import(RequiredCreationPolicy=CreationPolicy.NonShared)]
    private readonly IDbContext _context;

    public IRepository<T> CreateRepository<T>() where T : class, IEntity
    {
        IRepository<T> repo = _container.GetExportedValue<EntityRepository<T>>();
        repo.context = _context;

        return repo;
    }
}

其余的应该是自我解释的:

public  class   EntityRepository<T> :   IRepository<T>  where   T   :   class,  IEntity
{
    protected   IDbContext  _context;

    IDbContext  context
    {
        set {   _context    =   value;  }
    }

    public  virtual IQueryable<T>   GetQuery()
    {
        return  _context.Set<T>();
    }

    public  virtual T   GetById(Guid    id)
    {
        return  _context.Set<T>().Find(id);
    }

    public  virtual void    SaveOrUpdate(T  entity)
    {
        if  (_context.Set<T>().Find(entity.Id)  ==  null)
        {
            _context.Set<T>().Add(entity);
        }

        _context.SaveChanges();
    }

    public  virtual void    Delete(T    entity)
    {
        _context.Set<T>().Remove(entity);

        _context.SaveChanges();
    }
}

如果您以与我相同的方式使用它,我无法真正看到此实现的问题。工厂负责创建类,因此它可以负责设置上下文。 CreationPolicy应确保每个工厂都获得它自己的DbContext实例,然后将其降级到它的存储库,以便它们共享一个上下文。