【问题标题】:How to use Unity to resolve a new instance every time the old one get disposed每次处理旧实例时如何使用 Unity 解析新实例
【发布时间】:2010-11-13 21:21:19
【问题描述】:

我正在尝试开始使用 Unity,但我有一点把握。

我有一个 Context 类和一个由容器解析的 Repository 类。 我的 Repository 类将 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>

现在,我希望在调用 Resolve 并且旧的实例已经发布时构建 IGeneralContext 的新实例。

见:

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 解决它吗?

谢谢。

【问题讨论】:

    标签: dependency-injection unity-container ioc-container


    【解决方案1】:

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

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

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

    也可以扩展配置文件来为你做这件事。

    请参阅 CodePlex 上的 ctavares 帖子,他/她有一个非常好的示例。 http://unity.codeplex.com/Thread/View.aspx?ThreadId=219565

    【讨论】:

      【解决方案2】:

      看看 StaticFactory 扩展。您可以提供自己的对象创建方法,这样您就可以检测现有上下文是否仍然可用。

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

      【讨论】:

      • Thaks James,正如对 Steven 所说,我将 Unity 引入我的项目是为了简化我的设计。如果可能只通过配置 th XML 配置文件就可以了,我会发现最好继续这种方式。一旦不可能,我会将这些实例委托给工厂方法。
      【解决方案3】:

      您可能想退后一步,看看您的设计。我发现大多数时候我认为我需要一些复杂的 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();
          }
      }
      

      您可能还想尝试尽量减少对容器的调用量。尽量通过构造函数注入。

      Here is an interesting SO question 关于工作单元模式(= 上下文)和可能有用的存储库。

      我希望这会有所帮助。

      【讨论】:

      • Thaks Steven,非常有帮助。我使用 Unity 只是为了简化我的工作单元和存储库的实例化。一旦我没有其他理由走这条路,我发现最好使用一个简单的工厂(没有 Unity)来为开发人员完成这项工作。如果可以仅通过配置 XML 配置文件,甚至对我的设计进行一些调整,那将是非常好的。无论如何..非常感谢你!
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-04-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多