2016-09-03 66 views
-1

簡單DI例如:如何在這種情況下使用Castle Windsor類型的工廠?

public interface INumberToWordConverter 
{ 
    string ConvertNumber(int number); 
} 

public interface IOutputManager 
{ 
    void Write<T>(string who, T what); 
} 

public interface INumberProvider 
{ 
    int GenerateNumber(); 
} 

public class PlayWithDI 
{ 
    private IOutputManager _outputManagerService; 
    private INumberProvider _numberProviderService; 
    private INumberToWordConverter _numberToWordConverterService; 

    private PlayWithDI() { } 
    public PlayWithDI(
     IOutputManager outputManagerService, 
     INumberProvider numberProviderService, 
     INumberToWordConverter numberToWordConverterService) 
    { 
     if (outputManagerService == null) 
      throw new ArgumentNullException(nameof(outputManagerService)); 
     if (numberProviderService == null) 
      throw new ArgumentNullException(nameof(numberProviderService)); 
     if (numberToWordConverterService == null) 
      throw new ArgumentNullException(nameof(numberToWordConverterService)); 

     _outputManagerService = outputManagerService; 
     _numberProviderService = numberProviderService; 
     _numberToWordConverterService = numberToWordConverterService; 
    } 

    public void Execute() 
    { 
     int number = _numberProviderService.GenerateNumber(); 
     string wordOfNumber = _numberToWordConverterService.ConvertNumber(number); 
     _outputManagerService.Write(nameof(PlayWithDI), wordOfNumber); 
    } 

示例實現(只是構建函數):

// Implements INumberProvider 
public RandomNumberProvider(
     int min, int max, 
     IOutputManager outputManagerService) 
{ 
    ... 
} 

// Implements INumberToWordConverter 
public ItalianNumberToWordConverter(
     IOutputManager outputManagerService) 
{ 
    ... 
} 

// Implements IConsoleManager 
public ConsoleOutputManager() 
{ 
    ... 
} 

如果我知道這minmaxRandomNumberProvider,我只想解決這樣的:

public void Install(
     IWindsorContainer container, 
     IConfigurationStore store) 
    { 
     container.Register(
      Component.For<PlayWithDI>()); 

     container.Register(
      Component.For<IOutputManager>() 
      .ImplementedBy<ConsoleOutputManager>()); 

     container.Register(
      Component.For<INumberProvider>() 
      .ImplementedBy<RandomNumberProvider>() 
      .DependsOn(
       Dependency.OnValue("min", 2), 
       Dependency.OnValue("max", 20))); 

     container.Register(
      Component.For<INumberToWordConverter>() 
      .ImplementedBy<ItalianNumberToWordConverter>()); 
    } 

... 
container.Install(new DependenciesConfiguration1()); 
var testDI = container.Resolve<PlayWithDI>(); 
testDI.Execute(); 

問題出現時,我想給自定義p運行時參數爲RandomNumberProvider

我看了一下TypedFactory,但是在這個例子中我不太明白,因爲如果我先解決一個工廠,那麼我應該如何解決PlayWithDi?我應該傳遞給它的構造函數一個INumberProviderFactory而不是一個INumberProvider嗎?

在這種情況下,我想到了一個工廠是這樣的:

public interface INumberProviderFactory 
{ 
    INumberProvider Create(
     IOutputManager outputManager, 
     int min, int max); 
} 

當我再調用Create,我應該怎麼解決outputManager呢?我很困惑。

回答

1

問題出現時,我想在運行時給自定義參數RandomNumberProvider。

這是你出錯的地方。 Injecting runtime data into components during construction is ananti-pattern

不要在構造期間將運行時數據注入到應用程序組件中;它會導致模糊不清,使組成根源更加複雜,並且使您極其難以驗證DI配置的正確性。 [...]讓運行時數據流通過構造對象圖的方法調用。

換句話說,你RandomNumberProvider應該接受minmax論據是對GenerateNumber方法輸入參數。