我正在使用 CommonSrviceLocator 和 WindworContainer 来解析我的 NHibernage.ISession 实例。 ISession 实例是通过 SessionFactory 创建的。出于某种原因,我需要在一个应用程序中使用不同的数据库,因此我需要不同的连接字符串和不同的 NHibernate.ISession 对象。
SessionFactory 可以按数据库名称创建不同的 ISession 对象。所以我希望使用以下语法在我的应用程序中获得不同的 ISession 对象:
ISesssion sessionForDb1 = ServiceLocator.Current.GetInstance<ISession>("session-for-db1");
ISesssion sessionForDb2 = ServiceLocator.Current.GetInstance<ISession>("session-for-db2");
为了实现这一点,我创建了以下容器注册:
IWindsorContainer container = new WindsorContainer();
container.AddFacility<FactorySupportFacility>();
container.Register(
Component.For<ISessionFactory>()
.Named("session-factory-for-db1")
.LifeStyle.Singleton
.UsingFactoryMethod(() => new NHibernateConfigurator().CreateSessionFactoryForDb1()),
Component.For<ISessionFactory>()
.Named("session-factory2-for-db2")
.LifeStyle.Singleton
.UsingFactoryMethod(() => new NHibernateConfigurator().CreateSessionFactoryForDb2()),
Component.For<ISession>()
.Named("session-for-db1")
.LifeStyle.PerWebRequest
.UsingFactoryMethod(kernel => kernel.Resolve<ISessionFactory>("session-factory-for-db1").OpenSession()),
Component.For<ISession>()
.Named("session-for-db2")
.LifeStyle.PerWebRequest
.UsingFactoryMethod(kernel => kernel.Resolve<ISessionFactory>("session-factory2-for-db2").OpenSession())
);
ServiceLocator.SetLocatorProvider(() => new WindsorServiceLocator(container));
这是有效的,但我不喜欢的是我需要创建很多表示对象族的字符串常量,并使用另一个命名每个实例来构建每个对象。所以对于这个任务,我需要注册4个字符串常量,如果我的 SessionFactory 必须用另一个工厂创建,我可能需要定义6个常量等。
我想知道是否有更好的方法来注册类似的对象系列?
答案 0 :(得分:1)
当存在多个具有相同服务类型的服务时,您必须使用组件ID(字符串)来区分它们。在您的情况下,如果您从未将任何ISessionFactory直接注入到类中,则可以将此注册包装在扩展方法中,例如:
public static class WindsorSessionFactoryExtensions {
public static void RegisterSession(this IWindsorContainer container, string name, Func<NHibernateConfigurator, ISessionFactory> configurator) {
var id = Guid.NewGuid().ToString();
container.Register(
Component.For<ISessionFactory>()
.Named(id)
.LifeStyle.Singleton
.UsingFactoryMethod(() => configurator(new NHibernateConfigurator())),
Component.For<ISession>()
.Named(name)
.LifeStyle.PerWebRequest
.UsingFactoryMethod(k => k.Resolve<ISessionFactory>(id).OpenSession())
);
}
}
container.RegisterSession("session-for-db1", c => c.CreateSessionFactoryForDb1());
container.RegisterSession("session-for-db2", c => c.CreateSessionFactoryForDb2());
var session = container.Resolve<ISession>("session-for-db1");
或者不是使用GUID作为会话工厂ID,而是可以执行类似var id = name + "-factory"
之类的事情,例如约定。
另一种可能性是使用ExtendedProperties,但这可能会使事情变得更复杂,最终总会有某种鉴别器。
但这里真正的问题是你正在使用服务定位器。在正常的容器使用中,您永远不必使用它。而是使用服务覆盖来定义所需的注册组件会话。