Как правильно зарегистрировать несколько экземпляров одного и того же типа в контейнере Windsor? - PullRequest
1 голос
/ 28 июля 2010

Я использую 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 констант и т. Д.

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

1 Ответ

1 голос
/ 28 июля 2010

Когда есть несколько сервисов с одинаковым типом сервиса, вы должны использовать идентификатор компонента (строку) для их различения. В вашем случае, если вы никогда не внедрили какую-либо 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, но это могло бы еще больше усложнить ситуацию, и в итоге всегда должен быть какой-то дискриминатор.

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

...