MEF и динамическое решение по созданию экземпляра - PullRequest
1 голос
/ 11 октября 2011

Это может быть странным случаем, но я хочу иногда использовать один и тот же экземпляр при получении экспорта с помощью MEF, а иногда создавать новый.

В основном у меня есть класс обслуживания WCF, который является экземпляром на вызов. Каждый экземпляр импортирует RepositoryFactory, который также будет новым экземпляром для каждого класса обслуживания. Я возвращаю хранилище на фабрике, а хранилище получает IDbContext.

Я хочу, чтобы каждый экземпляр Фабрики вставлял один и тот же экземпляр IDbContext, но между экземплярами Фабрики были отдельные экземпляры.

Итак:

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, я не уверен, как бы я поступил так.


EDIT

Вот что я получил:

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 ]

1 голос
/ 12 октября 2011

Вы не можете сделать это с помощью MEF;Независимо от того, что вы делаете, контейнер MEF не будет работать правильно для вас как менеджер единиц работы, он просто не предназначен для этого.

Вы должны попытаться явно кодировать инфраструктуру единицы работы для вашего DALпотреблять.Ваши репозитории должны явно попросить менеджера единиц работы предоставить текущую единицу работы и вместе с ней соответствующий контекст.

Взгляните на код в NCommon https://github.com/riteshrao/ncommon;, который вы можете реорганизовать.функций работы для удовлетворения ваших потребностей.

0 голосов
/ 17 октября 2011

Хорошо, вот решение, которое я придумал, но еще не пробовал. Это несколько просто и на самом деле работает вокруг 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, который затем передается в свои репозитории, чтобы они имели общий контекст.

...