2015-06-29 67 views
4

我試圖找出將參數傳遞給構造函數的最佳(最好)方法自動解析參數的子對象。Castle Windsor:如何將參數傳遞給待解析類型的「子」項的構造函數

爲什麼? 因爲我有一個程序幾乎可以完成對同一個「生產」數據庫的所有計算(在配置文件中定義,因此不需要參數)。但現在需要在這個數據庫的「副本」上運行一些工作。因此需要不同的連接字符串。

連接字符串可以在構造函數中提供,並且在編譯時不知道。問題是我不能(或不知道如何)簡單地訪問這個構造函數,因爲它深埋在生成的項目中。

考慮以下(簡化的)的代碼片斷:

public class Example 
{ 
    protected readonly IGenerateSomethingFactory Factory; 
    public Example(IGenerateSomethingFactory factory) 
    { 
     Factory = factory; 
    } 

    public Task DoSomething(string ConnectionString, string a, string b) 
    { 
     //needs to run somehow using the supplied connection string ... 
     return Task.Run(() => Factory.CreateSomething().Execute(a, b)); 
     //= Task.Run(() => new Something(new UnitOfWork(new DataContext(ConnectionString))).Execute(a, b)); 
    } 

    public Task DoSomething(string a, string b) 
    { 
     //needs to run using the default connection string (defined in config) 
     return Task.Run(() => Factory.CreateSomething().Execute(a, b)); 
    } 
} 

的問題在第一DoSomething(...)函數規定。

注:溫莎城堡的安裝程序是這樣的:

public class Installer : IWindsorInstaller 
{ 
    public void Install(IWindsorContainer container, IConfigurationStore store) 
    { 
     container.AddFacility<TypedFactoryFacility>(); 
     container.Register(Component.For<IGenerateSomethingFactory>().AsFactory()); 
     container.Register(Classes.FromThisAssembly().InNamespace("x").WithService.FirstInterface()); 
    } 
} 

我正在尋找一個解決方案:

  • 是線程安全的
  • 很容易理解(如果不容易想想)
  • 允許重構(所以沒有命名參數像「conString」)
  • 不會r等於改變其他不相關的代碼 (即,設置屬性的公共...)
  • 不叫newcontainer.Resolve<>()

我一直在尋找到選擇處理程序,但還沒有真正找到了我一直在尋找。

PS:我使用溫莎城堡3.3.0

PPS:這是我的第一個問題,我可以提供更多的示例代碼,但我認爲應該限制到最小......所以讓我知道如果我需要這樣做。

+0

看來你可以在工廠的'CreateSomething'方法中添加'ConnectionString'作爲參數。或者我誤解了你的問題? –

+0

那麼我沒有創建工廠,它是由溫莎城堡自動生成的。另外,那麼我可能需要在容器上調用Resolve ,並確保我正確地執行所有清理。我是DI新手...... –

+0

對,但你定義了界面。閱讀[本節](https://github.com/castleproject/Windsor/blob/master/docs/typed-factory-facility-interface-based.md#resolving-with-arguments)和[本節](https: //github.com/castleproject/Windsor/blob/master/docs/typed-factory-facility-interface-based.md#method-parameters-are-forwarded-to-the-caller-by-name)。 –

回答

2

從你的榜樣,它看起來像所有你需要做的是一個參數添加到您的typed factory'sCreateSomething方法:

public interface IGenerateSomethingFactory 
{ 
    ISomething CreateSomething(string connectionString); 
} 

然後添加作爲參數傳遞給您的ISomething實現:

public class Something : ISomething 
{ 
    public Something(string connectionString) 
    { 
    } 
} 

請注意CreateSomethingSomething的構造函數的參數是如何命名的。 This is the default behavior for parameter matching

現在,你只要沿着您的通話值傳遞給DoSomething

public Task DoSomething(string ConnectionString, string a, string b) 
{ 
    return Task.Run(() => Factory.CreateSomething(ConnectionString).Execute(a, b)); 
} 

根據您添加的代碼,你想要做的是沒有立即可行的。概括地說,你有這樣的分辨等級:

  • IGenerateSomethingFactory.Create(string constring)
    • Something.ctor(IUnitOfWork uow)
      • UnitOfWork.ctor(IDataContext context)
        • DataContext.ctor(string constring)

你試圖通過從呼叫Create參數下降到DataContext構造。

有關啓用此功能的方法,請參閱my answer(適用於我自己的問題)。我這樣做是通過改變Windsor的默認行爲來將工廠創建參數傳遞給所有解析對象而不是第一個。

首先,創建這個類來改變這種行爲:

public class DefaultDependencyResolverInheritContext : DefaultDependencyResolver 
{ 
    protected override CreationContext RebuildContextForParameter(CreationContext current, Type parameterType) 
    { 
     if (parameterType.ContainsGenericParameters) 
     { 
      return current; 
     } 

     return new CreationContext(parameterType, current, true); 
    } 
} 

創建的貨櫃時,然後爲它供給:

var kernel = new DefaultKernel(
       new DefaultDependencyResolverInheritContext(), 
       new NotSupportedProxyFactory()); 
var container = new WindsorContainer(kernel, new DefaultComponentInstaller()); 

就是這樣。現在,當您調用Create方法時,constring參數將傳遞到所有正在註冊的對象。 顯然這可能會導致問題,如果你有參數是相同的名稱!在你的情況下,這是一個「環境」參數(我的術語),所以你可以只記錄這個行爲/參數名稱並稱之爲一天。

我很想看到另一種方法,除了爲所有中間類型創建工廠外。

+0

我剛剛試過這個,它不工作。我認爲這隻適用於你想要解析的對象的參數,並且它們不會傳遞到更遠處的其他對象... (在兩個構造函數中使用斷點測試,帶字符串參數的構造函數永遠不會被擊中) –

+0

然後你需要添加更多的代碼。您正在測試某些您沒有發佈過等效示例的內容。 –

+0

我已將所有測試類粘貼到粘貼箱[鏈接](http://pastebin.com/TitQv3uN)我已將斷點添加到第77和81行,並進入了Example.Run()方法。 PS:如果這是您想要/需要回答的代碼,我將使用此代碼更新問題。 –

相關問題