MEF 和实例创建的动态决策

发布于 2024-12-08 23:50:48 字数 1437 浏览 0 评论 0原文

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

基本上我有一个 WCF 服务类,它是每次调用的实例。每个实例都会导入一个 RepositoryFactory,它也将是每个服务类的新实例。我在工厂中返回一个存储库,并且存储库注入了 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;

This might be a strange case but I want to sometimes reuse the same instance when getting exports with MEF and sometimes create a new.

Basicly I have a WCF service class the is instance per call. Each instance imports a RepositoryFactory which will also be new instance per service class. I return a Repository in the Factory and a repository gets a IDbContext injected.

I want each instance of the Factory to inject the same instance of IDbContext but have seperate instances between Factory instances.

So:

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

This should ensures that Repositories created from the same factory share a Unit of Work.

But being new to MEF I'm not sure how I would go about doing that.


EDIT

This is what I got:

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>>();
    }
}

and then

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

北陌 2024-12-15 23:50:48

使用 MEF 无法完成此任务;无论您做什么,MEF 容器都不会正确地充当您的工作单元管理器,它不是为此而设计的。

您应该尝试显式地编写工作单元基础设施以供 DAL 使用。您的存储库应明确要求工作单元经理提供当前的工作单元及其适当的上下文。

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

You cannot accomplish this with MEF; no matter what you do the MEF container will not act correctly as a Unit of Work manager for you, it just isn't made for this.

You should attempt to explicitly code a Unit of Work infrastructure for your DAL to consume. Your repositories should explicitly ask the a Unit of Work Manager to provide a current Unit of Work and with it the appropriate context.

Take a look at the code in NCommon https://github.com/riteshrao/ncommon; you can refactor the Unit of Work features to serve your needs.

_失温 2024-12-15 23:50:48

好的,这是我想出的解决方案,但还没有尝试过。它有点简单,实际上可以在 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 应确保每个 Factory 获取其自己的 DbContext 实例,然后将其委托给其存储库,以便它们共享上下文。

OK here is a solution I came up with but haven't tried. It's somewhat simple and actually works around MEF but doesn't really break it, at least not in my case.

Add to IRepository class the following method:

void SetContext(IDbContext context);

or better yet

IDbContext context { set; }

and in the factory:

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;
    }
}

And the rest should be self explanatory:

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();
    }
}

If you are using it in the same way as I am I can't really see a problem with this implementation. The factory is responsible for creating the class so It can be responsible for setting the context. The CreationPolicy should ensure that each Factory gets it's own instance of DbContext that it then relegates to it's Repositories so they share a context.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文