Как использовать Unity для разрешения нового экземпляра каждый раз, когда удаляется старый - PullRequest
2 голосов
/ 14 ноября 2010

Я пытаюсь начать использовать Unity, но у меня есть запас в точке.

У меня есть класс Context и класс репозитория, который разрешается контейнером.Мой класс репозитория принимает параметр Context ctor в качестве зависимости.

Мой файл конфигурации:

контейнер:

  <register type="IGeneralContext" mapTo="Data.EF.EFContext, Data.EF">
    <lifetime type="singleton" />
    <constructor>
      <param name="connectionString">
        <value value="anyConnStr"/>
      </param>
    </constructor>
  </register>

  <register type="IClienteRepository" mapTo="Repository.EF.ClientRepository, Repository.EF">
    <constructor>
      <param name="context">
        <dependency type="Data.EF.EFContext, Data.EF"/>
      </param>
    </constructor>
  </register>

А теперь я хочучто новый экземпляр IGeneralContext создается, когда Resolve вызывается И старый уже выпущен.

См .:

using (IGeneralContext context = container.Resolve<IGeneralContext>()) //NEW CONTEXT INSTANCE
{
    IClienteRepository rep = container.Resolve<IClienteRepository>(); // USE DEPENDENCY AS SINGLETON
    Cliente nc = new Cliente() {  };
    rep.Add(nc);
    context.CommitChanges();
} // DISPOSE CONTEXT

using (IGeneralContext context = container.Resolve<IGeneralContext>()) //BRAND NEW CONTEXT INSTANCE
{
    IClienteRepository rep = container.Resolve<IClienteRepository>(); // USE DEPENDENCY AS SINGLETON
    Cliente nc = new Cliente() { };
    rep.Add(nc);
    context.CommitChanges();
} // DISPOSE CONTEXT

IClienteRepository rep1 = container.Resolve<IClienteRepository>(); // NEW CONTEXT AGAIN
Cliente cliente1= rep1.GetById(1);

Есть идеи, как решить его с помощью Unity?

Tks.

Ответы [ 3 ]

4 голосов
/ 16 ноября 2010

Проанализировав лучшее предложение Джеймса, я нашел хорошую альтернативу.

Существует новый способ делегировать экземпляры фабрике:

        container.RegisterType<IMyInterface, MyConcrete>(new InjectionFactory(c => MyFactoryClass.GetInstance()));

А также возможно расширить файл конфигурации, чтобы сделать это для вас.

См. Сообщение ctavares на CodePlex, у него очень хороший пример. http://unity.codeplex.com/Thread/View.aspx?ThreadId=219565

1 голос
/ 14 ноября 2010

Возможно, вы захотите сделать шаг назад и взглянуть на свой дизайн. Я обнаружил, что большую часть времени я думал, что мне нужна сложная конфигурация DI, проблема была на самом деле в моем дизайне. Вот несколько вариантов, которые вы могли бы рассмотреть:

1) Используйте фабрику для создания репозиториев и предоставьте контекст для этой фабрики:

var repositoryFactory = container.Resolve<IRepositoryFactory>();

using (var context = container.Resolve<IGeneralContext>())
{
    var rep = repositoryFactory.Create<IClienteRepository>(context);
    // ...
}

public class RepositoryFactory : IRepositoryFactory
{
    public TRepository Create<TRepository>(IGeneralContext context)
        where TRepository : IRepository
    {
        var repository = Container.Resolve<TRepository>();
        repository.Context = context;
        return repository;
    }
}

2) Попробуйте сделать репозитории частью контекста:

using (var context = container.Resolve<IGeneralContext>())
{
    var nc = new Cliente() { };
    context.Clientes.Add(nc);
    // ...
}

Если невозможно поместить все эти свойства репозитория в сам контекст, вы можете создать объект-оболочку:

using (var context = container.Resolve<NorthwindContext>())
{
    var nc = new Cliente() { };
    context.ClienteRepository.Add(nc);

    // ...
}

public class NorthwindContext
{
    private IGeneralContext context;
    private IRepositoryFactory repFactory;

    public NorthwindContext(IGeneralContext context,
        IRepositoryFactory repFactory)
    {
        this.context = context;
        this.repFactory = repFactory;
    }

    public IClienteRepository Clientes
    {
        get { return this.repFactory
            .Create<IClienteRepository>(this.context); }
    }

    public IOrderRepository Orders
    {
        get { return this.repFactory
            .Create<IOrderRepository>(this.context); }
    }

    public void CommitChanges()
    {
        this.context.CommitChanges();
    }
}

Вы также можете попытаться свести к минимуму количество вызовов в контейнер. Попробуйте ввести столько, сколько сможете через конструктор.

Вот интересный вопрос SO о шаблоне Единицы работы (= контекст) и репозиториях, которые могут быть полезны.

Надеюсь, это поможет.

1 голос
/ 14 ноября 2010

Посмотрите на расширение StaticFactory.Вы должны предоставить свой собственный метод для создания объекта, который позволит вам определить, доступен ли существующий контекст.

http://www.pnpguidance.net/post/RegisteringFactoryMethodCreateObjectsUnityStaticFactoryExtension.aspx

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...