StructureMap: Choose concrete type of nested dependency

試著忘記壹切 提交于 2019-12-19 19:51:31

问题


Calculators:

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

Calculator 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;
    }
}

Calculator usages:

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

Structuremap Registry:

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

For CalculatorUsageOne I want to add the numbers (use AdditionCalculator). For CalculatorUsageTwo I want to multiply the numbers (use MultiplyCalculator).

How do I achieve this with StructureMap?


回答1:


Try like this:

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

You can nest your objects graph configurations as deep as you need. Anyway, I would think about using generics here to show the dependencies in more explicit way.

edit about generics:

Whether using generics is a good idea here depends from your scenario. If you didn't specified the concrete dependencies for your CalculatorUsages on purpose and that's your goal to have it strategy-agnostic, your solution seems to be the best.

But if you just need to have common implementation of Calculator in "middle layer", you can specify Calculator's dependency in generic parameter to make it explicit. Maybe it's not the best use case here, but it can go somehow like this:

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

public class Calculator<T> where T : ICalculatorStrategy
{
    public Calculator(T strategy)
    {
        // ...
    }
}

and register it like this:

For(typeof(ICalculator<>).Use(typeof(Calculator<>);

This will tell StructureMap to pass any generic parameter for requested ICalculator to Calculator (open generics), which then instantiates the strategy objects in constructor.

Alternatively, you can use marker interfaces instead of generics, but once again, it all depends from your particular scenario and it may be that the simplest solution from very beginning fits best.




回答2:


One method is to define the dependency when getting an instance using the With method.

var additionStrategy = ObjectFactory
                            .GetNamedInstance<ICalculatorStrategy>("Addition");
var c1 = ObjectFactory.With(additionStrategy).GetInstance<CalculatorUsageOne>();

The only other way I can think of is providing the isntances as constructor arguments when registering the types. I can provide an example tomorrow.



来源:https://stackoverflow.com/questions/6575883/structuremap-choose-concrete-type-of-nested-dependency

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!