2010-11-23 127 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))