在这种情况下如何使用温莎城堡类型的工厂

本文关键字:城堡 类型 工厂 这种情况下 何使用 | 更新日期: 2023-09-27 18:05:41

简单的DI示例:

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()
{
    ...
}

如果我知道哪个minmax给了RandomNumberProvider,我就像这样解析:

    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();

当我想在运行时为RandomNumberProvider提供自定义参数时,问题就出现了。

我看了看TypedFactory,但在这个例子中我真的不理解它,因为如果我先解决一个工厂,我应该如何解决PlayWithDi?我应该传递给它的构造器INumberProviderFactory而不是INumberProvider吗?

在这种情况下,我想到了这样一个工厂:

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

当我调用Create时,我该如何解决outputManager呢?我困惑。

在这种情况下如何使用温莎城堡类型的工厂

当我想在运行时给RandomNumberProvider自定义参数时,问题就出现了。

这就是你错的地方。在构造期间向组件注入运行时数据是一种反模式:

不要在构建过程中向应用程序组件注入运行时数据;它会导致歧义,使组合根具有额外的责任,并且使验证DI配置的正确性变得异常困难。[…让运行时数据流过构造对象图的方法调用。

换句话说,您的RandomNumberProvider应该接受minmax参数作为GenerateNumber方法的输入参数。