StructureMap:选择嵌套依赖项的具体类型

Roo*_*ian 5 c# structuremap dependency-injection constructor-injection

计算器:

public interface ICalculator
{
    int Calculate(int a, int b);
}

public class Calculator : ICalculator
{
    private readonly ICalculatorStrategy _calculatorStrategy;

    public Calculator(ICalculatorStrategy calculatorStrategy)
    {
        _calculatorStrategy = calculatorStrategy;
    }

    public int Calculate(int a, int b)
    {
        return _calculatorStrategy.Calculate(a, b);
    }
}
Run Code Online (Sandbox Code Playgroud)

计算器stragies:

public interface ICalculatorStrategy
{
    int Calculate(int a, int b);
}

public class AdditionCalculator : ICalculatorStrategy
{
    public int Calculate(int a, int b)
    {
        return a + b;
    }
}

public class MultiplyCalculator : ICalculatorStrategy
{
    public int Calculate(int a, int b)
    {
        return a * b;
    }
}
Run Code Online (Sandbox Code Playgroud)

计算器用法:

public class CalculatorUsageOne
{
    private readonly ICalculator _calculator;

    public CalculatorUsageOne(ICalculator calculator)
    {
        _calculator = calculator;
    }

    public void Process()
    {
        Console.WriteLine(_calculator.Calculate(6, 5));
    }
}

public class CalculatorUsageTwo
{
    private readonly ICalculator _calculator;

    public CalculatorUsageTwo(ICalculator calculator)
    {
        _calculator = calculator;
    }

    public void Process()
    {
        Console.WriteLine(_calculator.Calculate(6, 5));
    }
}
Run Code Online (Sandbox Code Playgroud)

结构图注册表:

public class DependencyRegistry : Registry
{
    public DependencyRegistry()
    {
        For<ICalculatorStrategy>().Use<AdditionCalculator>().Named("Addition");
        For<ICalculatorStrategy>().Use<MultiplyCalculator>().Named("Multiply");
        For<ICalculator>().Use<Calculator.Calculator>();
    }
}
Run Code Online (Sandbox Code Playgroud)

对于CalculatorUsageOne,我想添加数字(使用AdditionCalculator).对于CalculatorUsageTwo我想要乘以数字(使用MultiplyCalculator).

我如何使用StructureMap实现这一目标?

NOt*_*Dev 4

尝试这样:

For<CalculatorUsageOne>().Use<CalculatorUsageOne>()
    .Ctor<ICalculator>().Is<Calculator.Calculator>(
        x => x.Ctor<ICalculatorStrategy>().Is<AdditionCalculator>()
    );
For<CalculatorUsageTwo>().Use<CalculatorUsageTwo>()
    .Ctor<ICalculator>().Is<Calculator.Calculator>(
        x => x.Ctor<ICalculatorStrategy>().Is<MultiplyCalculator>()
    );
Run Code Online (Sandbox Code Playgroud)

您可以根据需要嵌套对象图配置的深度。不管怎样,我会考虑在这里使用泛型来以更明确的方式显示依赖关系。

编辑关于泛型:

使用泛型是否是一个好主意取决于您的场景。如果您没有故意指定具体的依赖项,CalculatorUsages并且您的目标是使其与策略无关,那么您的解决方案似乎是最好的。

但是,如果您只需要Calculator在“中间层”中具有通用的实现,则可以Calculator在通用参数中指定 的依赖关系以使其显式化。也许这不是最好的用例,但它可以像这样:

public class CalculatorUsageOne
{
    public CalculatorUsageOne(ICalculator<AdditionCalculator> calculator)
    {
        // ...
    }
}

public class Calculator<T> where T : ICalculatorStrategy
{
    public Calculator(T strategy)
    {
        // ...
    }
}
Run Code Online (Sandbox Code Playgroud)

并像这样注册:

For(typeof(ICalculator<>).Use(typeof(Calculator<>);
Run Code Online (Sandbox Code Playgroud)

这将告诉 StructureMap 将请求的任何泛型参数传递给ICalculatorCalculator开放泛型),然后在构造函数中实例化策略对象。

或者,您可以使用标记接口而不是泛型,但这一切都取决于您的特定场景,并且可能从一开始最简单的解决方案就最适合。