2010-11-23 95 views
1

我在种姓温莎XML配置定义为我的应用以下三个部分组成:帮助与温莎城堡XML配置

<component id="StringFactory" 
      service="IStringFactory, MyApp" 
      type="DefaultStringFactory, MyApp" 
      lifestyle="singleton" 
      /> 

<component id="TheString" 
      type="System.String" 
      factoryId="StringFactory" 
      factoryCreate="CreateString" 
      > 
    <parameters> 
    <name>SomeString</name> 
    </parameters> 
</component> 

<component id="TheTarget" 
      service="ITarget, MyApp" 
      type="TheTarget, MyApp" 
      lifestyle="transient" 
      > 
    <parameters> 
    <aString>${TheString}</aString> 
    </parameters> 
</component> 

及以下设备定义:

<facility id="factory.support" 
      type="Castle.Facilities.FactorySupport.FactorySupportFacility, Castle.MicroKernel" 
      /> 

当我运行应用程序并在TheObject类的构造函数中设置一个断点,当我希望它解析为具有该名称的组件的值时,传递的值为aString参数为“$ {TheString}”。

另外,我在StringFactory构造函数和CreateString方法中都有一个断点,它们都没有命中。我知道正在使用配置,因为其他组件正在正确解析。

我在这里失踪或做错了什么?

UPDATE

在巨大tangient这个话题已经采取的光,我已经重构上面的代码删除任何与连接字符串。这篇文章的原意是关于用另一个对象的方法返回的值注入一个属性。不知何故,这一点在关于为什么我使用XML与基于代码的配置以及如果这是注入连接字符串的好方法的讨论中丢失了。

上述方法与最初的想法并不相同,它是从其他几个关于此主题的讨论中拉出来的,我们的要求就是它们的要求。我希望帮助您理解配置的原因(无论正确的方法与否)未按预期工作。

我确实验证了前两个组件正在正确实例化。当我调用Container.Resolve(“TheString”)时,我得到了正确的值。无论出于何种原因,参数语法无法正常工作。

任何想法?

+0

您是否因任何特定原因使用XML注册? – 2010-11-23 18:40:33

+0

解决方案要求。应用程序必须无需重新编译即可重新配置。 – SonOfPirate 2010-11-23 18:46:38

+0

您确定要配置像GetConnectionString或IConfigurationService,MyApp吗?您可以在Windsor中混合使用代码和XML配置。 – 2010-11-23 18:49:51

回答

2

虽然不是在我的应用程序中需要做的最终解决方案,我相信我已经找出了代码中的错误。或者至少我已经找到了一种方法来使它工作,这暗示了最初的问题。

我用自定义类替换了TheString的String类型。而已。一旦我这样做,一切运作良好。

我的猜测是它与我试图使用ValueType(基元)作为组件的事实有关。我想Castle不支持它。因此,如果知道这种情况,我现在可以继续研究这种方法是否真的有效,或者我们需要改变方向。

UPDATE

为了完整起见,我想我会继续前进,并解释我做了什么来解决我的问题,满足我的要求。

如前所述,我通过IConfigurationService访问我的配置设置定义为:

<component id="ConfigurationService" 
      service="MyApp.IConfigurationService, MyApp" 
      type="MyApp.RuntimeConfigurationService, MyApp" 
      lifestyle="singleton" 
      /> 

这是自动注入到我的(新)IConnectionFactory其负责基于所定义的连接字符串生成的IDbConnection对象在应用程序的配置文件中。工厂声明为:完全

<component id="MyDbConnection" 
      type="System.Data.IDbConnection, 
       System.Data, Version=2.0.0.0, Culture=neutral, 
       PublicKeyToken=b77a5c561934e089" 
      factoryId="ConnectionFactory" 
      factoryCreate="CreateConnection" 
      lifestyle="transient" 
      > 
    <parameters> 
    <connectionStringName>MyDB</connectionStringName> 
    </parameters> 
</component> 

注意:

<component id="ConnectionFactory" 
      service="MyApp.Factories.IConnectionFactory, MyApp" 
      type="MyApp.Factories.DefaultConnectionFactory, MyApp" 
      lifestyle="singleton" 
      /> 

为了解决用什么连接通过我的仓库,我使用的ConnectionFactory创建每个实例声明每个连接的组件描述对System.Data的引用。我发现无论何时在GAC中引用程序集,都是必要的。

最后,我的仓库被定义为:

<component id="MyRepository" 
      service="MyApp.Repositories.IMyRepository, MyApp" 
      type="MyApp.Sql.SqlMyRepository, MyApp.Sql" 
      lifestyle="transient" 
      > 
    <parameters> 
    <connection>${MyDbConnection}</connection> 
    </parameters> 
</component> 

现在一切都正确解析,我没有编入我的代码的任何硬编码字符串。没有连接字符串名称,应用程序设置键或其他。该应用程序可以从XML文件完全重新配置,这是我必须满足的要求。另外,将与解决方案一起工作的其他开发人员可以以他们习惯的方式管理实际的连接字符串。双赢。

希望这可以帮助任何遇到类似情况的人。

1

因为您可能不需要交换组件或更改使用的方法而无需重新编译,所以您不需要在此处进行XML注册。编写可配置的应用程序并不意味着必须使用XML注册。

与你张贴了这个特定的XML注册的问题是,在连接字符串是参数,但它像对待服务

与代码注册这样做要容易得多,例如:

var container = new WindsorContainer(); 
container.Register(Component.For<IConfigurationService>().ImplementedBy<RuntimeConfigurationService>()); 
container.Register(Component.For<ITheRepository>().ImplementedBy<TheRepository>() 
          .LifeStyle.Transient 
          .DynamicParameters((k, d) => { 
           var cfg = k.Resolve<IConfigurationService>(); 
           d["connectionString"] = cfg.GetConnectionString(); 
           k.ReleaseComponent(cfg); 
          })); 

或者,如果你不想依赖于IConfigurationService,你可以这样做:

container.Register(Component.For<ITheRepository>().ImplementedBy<TheRepository>() 
          .LifeStyle.Transient 
          .DependsOn(Property.ForKey("connectionString")            
               .Is(ConfigurationManager.ConnectionStrings[ConfigurationManager.AppSettings["connName"]].ConnectionString))