2010-07-28 2 views
1

Я использую CommonSrviceLocator с WindworContainer для решения моих NHibernage.ISession экземпляров. ISession экземпляры создаются через SessionFactory. По какой-то причине мне нужно работать с разными базами данных в одном приложении, поэтому мне нужны разные строки подключения и разные объекты. NHibernate.ISession объектов.Что такое правильный подход для регистрации нескольких экземпляров одного и того же типа в контейнере Windsor?

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 констант и т. Д.

Я хотел бы знать, есть ли какой-либо лучший подход для регистрировать похожие семейства объектов?

ответ

1

Если существует несколько служб с одинаковым типом службы, вы должны использовать идентификатор компонента (string) для их различения. В вашем случае, если вы никогда не вводить какие-либо 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 для сеанса заводского идентификатора, вы могли бы сделать что-то подобный var id = name + "-factory" вид товара, подобный соглашение.

Другая возможность - использовать ExtendedProperties, но это может усложнить ситуацию еще больше, и в конце концов всегда должен быть какой-то дискриминатор.

Но настоящая проблема заключается в том, что вы используете локатор сервисов. В обычном использовании контейнера вам никогда не придется использовать его. Вместо этого используйте переопределения служб, чтобы определить, какой сеанс вы хотите использовать в своих зарегистрированных компонентах.

+0

Большое спасибо, не могли бы вы охарактеризовать свое мнение об локаторе обслуживания в нескольких словах. Почему я не должен его использовать? И как применяется переопределение обслуживания в этой ситуации? – Restuta

+0

re service locator, см. Http://blog.ploeh.dk/2010/02/03/ServiceLocatorIsAnAntiPattern.aspx –

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