温莎城堡“后期绑定”组件

时间:2012-05-14 08:35:56

标签: c# .net nhibernate inversion-of-control castle-windsor

我的容器中注册了几个组件,Windsor可以毫无问题地注入它们。 现在我以这种方式为NHibernate ISessionFactory添加了一个新注册:

foreach (KeyValuePair<string, string> _tenantItem in _contextWrapper.TenantsConnectionStrings)
        {
            var config = Fluently.Configure()
                .Database(
                    MsSqlConfiguration.MsSql2008
                    .UseOuterJoin()
                    .ConnectionString(_tenantItem.Value)
                    .FormatSql()
                    .ShowSql()
                )

                .ExposeConfiguration(ConfigurePersistence)
                .ProxyFactoryFactory(typeof(ProxyFactoryFactory))
                .BuildConfiguration();

            Kernel.Register(
                Component.For<ISessionFactory>()
                    .UsingFactoryMethod(config.BuildSessionFactory)
                    .Named(_tenantItem.Key)
                    .LifestyleTransient()
                    );
        }

现在,如果我尝试检查我的容器,我会看到:

enter image description here

组件实现是“后期绑定”,Windsor不会注入它。

怎么了?我可以检查什么?

2 个答案:

答案 0 :(得分:3)

这里有两个独立且无关的问题,让我依次回答。

“后期绑定”正如组件描述所说,仅仅意味着Windsor不会静态地知道ISessionFactory的实现类型。这不是一个值得关注的理由。

在您的情况下,您只需指定工厂方法config.BuildSessionFactory()即可构建实例,并且每次都可能不是同一类型。

可以实现工厂方法,如:

public ISessionFactory BuildSessionFactory()
{
   if (Today == DayOfWeek.Friday)
   {
      return new BeerOClockSessionFactory();
   }
   return SomeOtherSessionFactory();
}

这很好而且很正常。

您提到的另一个问题是,您可能会遇到意外行为,其中ISessionFactory的依赖性未达到预期效果。

可悲的是,除非你详细解释它,否则分享你所看到的那种错误我不认为除了说“它应该有效”之外我还能做些什么。

同样在我们参与其中的时候,我全心全意地同意@raulg的观点,认为会话工厂瞬态并不是一个特别好的主意。

答案 1 :(得分:2)

您可能不喜欢在运行时创建配置实例。

最好为配置创建一个合适的类,将其注册到容器中,然后使用它创建ISessionFactory实例。

public class MySessionFactoryBuilder : IMySessionFactoryBuilder
{
    private FluentConfiguration _fluentConfiguration = null;

    public MySessionFactoryBuilder()
    {
    }

    void Initialize(string connectionStringKey)
    {
        IPersistenceConfigurer persistenceConfigurer = null;

        persistenceConfigurer = MsSqlConfiguration.MsSql2008
                .UseOuterJoin()
                .ConnectionString(connectionStringKey)
                .FormatSql()
                .ShowSql()
                ;

        _fluentConfiguration = Fluently.Configure()
            .Database(persistenceConfigurer)
            .ExposeConfiguration(ConfigurePersistence)
            .ProxyFactoryFactory(typeof(ProxyFactoryFactory))
            .BuildConfiguration()
            ;
    }

    public ISessionFactory BuildSessionFactory(string connectionStringKey)
    {
        Initialize(connectionStringKey);
        return _fluentConfiguration.BuildSessionFactory();
    }

}

您可以正常注册。然后在安装程序循环中注册多个ISessionFactory,每个租户一个:

foreach (KeyValuePair<string, string> _tenantItem in _contextWrapper.TenantsConnectionStrings)
{

    container.Register(
    Component.For<ISessionFactory>()
        .UsingFactoryMethod(k => k.Resolve<MySessionFactoryBuilder>().BuildSessionFactory(_tenantItem.Value))
        .Named(_tenantItem.Key),

    Component.For<ISession>()
        .UsingFactoryMethod(k => k.Resolve<ISessionFactory>().OpenSession())
        .Named(_tenantItem.Key + "-nhsession")
        .LifeStyle.Transient
        );

}

注意,我注册了ISession瞬态,但没有注册ISessionFactory。通常,您希望尽可能长时间地保留ISessionFactory,因为创建它很昂贵。

我还没有对它进行过测试,但我猜它会解决它,因为会话工厂构建器的实现在编译时是已知的。