2010-07-28 49 views
1

我使用CommonSrviceLocatorWindworContainer解決我NHibernage.ISession實例。 ISession實例通過SessionFactory創建。出於某種原因,我需要在一個應用程序中使用不同的數據庫,所以我需要不同的連接字符串和不同的對象。在Windsor Container中註冊幾個相同類型的實例的正確方法是什麼?

SessionFactory可以通過DB名稱創建不同的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個常數等創建

我想知道是否有任何更好的方法註冊類似的對象系列?

回答

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,但這可能會使事情更加複雜,最後總會有某種鑑別器。

但是這裏真正的問題是您正在使用服務定位器。在正常的容器使用情況下,你不應該使用它。相反,使用服務覆蓋來定義您想要註冊的組件中的會話。

+0

非常感謝,你能用更多的話來形容你對服務定位器的看法。爲什麼我不需要使用它?在這種情況下服務覆蓋如何應用? – Restuta 2010-07-28 15:22:54

+0

重新服務定位器,請參閱http://blog.ploeh.dk/2010/02/03/ServiceLocatorIsAnAntiPattern.aspx – 2010-07-28 15:53:54

+0

重新服務覆蓋:請參閱http://stw.castleproject.org/Windsor.Registering-components-one-by -one.ashx#Supplying_the_component_for_a_dependency_to_use_Service_override_9 http://blog.bittercoder.com/PermaLink,guid.6c1a25f7-5c8c-4a5e-bda9-04ffa944ebd0.aspx – 2010-07-28 16:04:55

相關問題