如何在Unity中配置多个连接工厂

本文关键字:连接 工厂 配置 Unity | 更新日期: 2023-09-27 18:22:33

我有两个域,通过两个应用程序接口IA1IA2访问,它们分别使用不同的存储库R1R2。存储库使用一个接口来创建NHibernate会话ISimpleSessionFactory

如果存储库共享一个数据库,我会使用统一容器将它们设置为这样:

var unity = new UnityContainer();
unity.RegisterType<ISimpleSessionFactory, NHibernateSessionFactory>(
                new ContainerControlledLifetimeManager(), new InjectionConstructor("ConnectionA"));
unity.RegisterType<IA1, A1>();
unity.RegisterType<R1>();
unity.RegisterType<IA2, A2>();
unity.RegisterType<R2>();

但它们不共享连接字符串,所以我想做这样的事情:

var unity = new UnityContainer();
var child1 = unity.CreateChildContainer();
child1.RegisterType<ISimpleSessionFactory, NHibernateSessionFactory>(
                new ContainerControlledLifetimeManager(), new InjectionConstructor("ConnectionA"));
child1.RegisterType<IA1, A1>();
child1.RegisterType<R1>();
var child2 = unity.CreateChildContainer();
child2.RegisterType<ISimpleSessionFactory, NHibernateSessionFactory>(
                new ContainerControlledLifetimeManager(), new InjectionConstructor("ConnectionB"));
child2.RegisterType<IA2, A2>();
child2.RegisterType<R2>();

然而,我的问题是,我想从A1类中解决IA2。理想情况下,我希望除了会话工厂之外的所有东西都在父容器中。只是存储库R1R2需要不同的ISimpleSessionFactory,但据我所知,如果不在child中本地解析,它只会回到parent,所以如果我将任何内容移动到parent,它就找不到会话工厂。

如何在Unity中配置多个连接工厂

如果我正确理解您的问题,我相信您可以使用命名注册,而不需要两个单独的接口:

  // first named registration
  child1.RegisterType<ISimpleSessionFactory, NHibernateSessionFactory>(
            new ContainerControlledLifetimeManager(), 
            new InjectionConstructor("ConnectionA"), "ConnectionA");
  child1.RegisterType<IA1, A1>( new InjectionConstructor( new ResolvedParameter<ISimpleSessionFactory>("ConnectionA"));
  child1.RegisterType<R1>( new InjectionConstructor( new ResolvedParameter<ISimpleSessionFactory>("ConnectionA") );
  // the same goes for the second one, just create a named registration 
  // under a different name

这里的技巧是注册IA1R1(分别为IA2/R2),以便您精确地指出应该如何解析参数(ResolvedParameter指向命名注册)。

请注意,如果服务的构造函数具有更多参数,则InjectionConstructor不可用。在这种情况下,使用InjectionFactories代替

  child1.RegisterType<IA1, A1>( 
     new InjectionFactory( container => 
         {
             // arbitrarily complicated imperative code to create an instance
             // first resolve ISimpleSessionFactory by name
             ISimpleSessionFactory factory = 
                container.Resolve<ISimpleSessionFactory>( "ContainerA" );
             // then create A1
             return new A1( factory, any, other, parameters, here );
         }
     ) );

在得到更好的答案之前,我一直在做这件事,为两个会话工厂定义单独的接口,以便它们都可以在同一个容器中注册。

interface IASessionFactory : ISimpleSessionFactory{}
interface IBSessionFactory : ISimpleSessionFactory{}
class ASessionFactory : NHibernateSessionFactory, IASessionFactory{...}
class BSessionFactory : NHibernateSessionFactory, IBSessionFactory{...}
var unity = new UnityContainer();
unity.RegisterType<IASessionFactory, ASessionFactory>(
                new ContainerControlledLifetimeManager(), new InjectionConstructor("ConnectionA"));
unity.RegisterType<IBSessionFactory, BSessionFactory>(
                new ContainerControlledLifetimeManager(), new InjectionConstructor("ConnectionB"));
unity.RegisterType<IA1, A1>();
unity.RegisterType<R1>();
unity.RegisterType<IA2, A2>();
unity.RegisterType<R2>();

R1R2必须使用IASessionFactoryIBSessionFactory,而不是ISimpleSessionFactory