Dependency injection 如何在每次处理旧实例时使用Unity解决新实例

Dependency injection 如何在每次处理旧实例时使用Unity解决新实例,dependency-injection,unity-container,ioc-container,Dependency Injection,Unity Container,Ioc Container,我试图开始使用Unity,但我得到了一个要点 我有一个上下文类和一个由容器解析的存储库类。 我的存储库类将上下文参数作为依赖项 我的配置文件: 容器: <register type="IGeneralContext" mapTo="Data.EF.EFContext, Data.EF"> <lifetime type="singleton" /> <constructor> <param name="connection

我试图开始使用Unity,但我得到了一个要点

我有一个上下文类和一个由容器解析的存储库类。 我的存储库类将上下文参数作为依赖项

我的配置文件:

容器:

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

现在,我希望在调用Resolve时构造一个新的IGeneralContext实例,而旧实例已经发布

见:

使用(IGeneralContext context=container.Resolve())//新上下文实例
{
iclienterpository rep=container.Resolve();//将依赖项用作单例
Cliente nc=新的Cliente(){};
代表添加(nc);
context.CommitChanges();
}//处置上下文
使用(IGeneralContext context=container.Resolve())//全新的上下文实例
{
iclienterpository rep=container.Resolve();//将依赖项用作单例
Cliente nc=新的Cliente(){};
代表添加(nc);
context.CommitChanges();
}//处置上下文
iclienterpository rep1=container.Resolve();//新语境
Cliente client1=rep1.GetById(1);
你知道如何用统一来解决吗


Tks

看看StaticFactory扩展。您需要提供自己的对象创建方法,该方法允许您检测现有上下文是否仍然可用


您可能想后退一步,看看您的设计。我发现,大多数时候我认为我需要一些复杂的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;
    }
}
var repositoryFactory=container.Resolve();
使用(var context=container.Resolve())
{
var rep=repositoryFactory.Create(上下文);
// ...
}
公共类存储工厂:IRepositoryFactory
{
公共存储创建(IGeneralContext上下文)
在哪里存储:i存储
{
var repository=Container.Resolve();
Context=Context;
返回存储库;
}
}
2) 尝试使存储库成为上下文的一部分:

using (var context = container.Resolve<IGeneralContext>())
{
    var nc = new Cliente() { };
    context.Clientes.Add(nc);
    // ...
}
使用(var context=container.Resolve())
{
var nc=新客户机(){};
context.clients.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();
    }
}
使用(var context=container.Resolve())
{
var nc=新客户机(){};
context.clientrepository.Add(nc);
// ...
}
公共类NorthwindContext
{
私有IGeneralContext上下文;
私营电子零售工厂;
公共NorthwindContext(IGeneralContext上下文,
IRepositoryFactory(工厂)
{
this.context=上下文;
this.repFactory=repFactory;
}
公众客户
{
获取{返回此.repFactory
.Create(this.context);}
}
公共存储库订单
{
获取{返回此.repFactory
.Create(this.context);}
}
公共无效佣金()
{
this.context.CommitChanges();
}
}
您可能还希望尽量减少对容器的调用量。尝试通过构造函数注入尽可能多的内容

关于可能有用的工作单元模式(=上下文)和存储库


我希望这能有所帮助。

在分析了更好的詹姆斯建议后,我找到了一个好的替代方案

有一种新方法可以将实例化委托给工厂:

        container.RegisterType<IMyInterface, MyConcrete>(new InjectionFactory(c => MyFactoryClass.GetInstance()));
container.RegisterType(新注入工厂(c=>MyFactoryClass.GetInstance());
此外,还可以扩展配置文件来为您执行此操作

参见CodePlex的ctavares帖子,他/她有一个很好的例子。

Thaks Steven,这很有帮助。我使用Unity只是为了简化我的工作单元和存储库的实例化。一旦我没有其他理由这样做,我发现最好使用一个简单的工厂(没有统一性)为开发人员完成工作。如果只需要配置XML配置文件,甚至在我的设计中稍加调整,就可以了。无论如何非常感谢你!Thaks James告诉Steven,我把Unity带到了我的项目中,以简化我的设计。如果可能的话,只需配置th XML配置文件,我会发现最好继续这样做。一旦不可能,我将把这些实例化委托给工厂方法。
        container.RegisterType<IMyInterface, MyConcrete>(new InjectionFactory(c => MyFactoryClass.GetInstance()));