StructureMap: выберите конкретный тип вложенной зависимости - PullRequest
5 голосов
/ 05 июля 2011

Калькулятор:

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

Калькулятор страги:

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

Использование калькулятора:

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

Структура карты реестра:

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

Для CalculatorUsageOne Я хочу добавить цифры (используйте AdditionCalculator ). Для CalculatorUsageTwo я хочу умножить числа (используйте MultiplyCalculator ).

Как мне добиться этого с StructureMap?

Ответы [ 2 ]

4 голосов
/ 05 июля 2011

Попробуйте так:

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

Вы можете вкладывать конфигурации графа объектов так глубоко, как вам нужно.В любом случае, я бы подумал об использовании обобщений здесь, чтобы показать зависимости более явным образом.

редактировать о дженериках:

Является ли использование дженериков хорошей идеей, зависит от вашего сценария.Если вы не указали конкретные зависимости для вашего CalculatorUsages специально, и ваша цель - сделать его независимым от стратегии, ваше решение кажется лучшим.

Но если вам просто нужна общая реализация Calculator в «среднем слое», вы можете указать зависимость Calculator в универсальном параметре, чтобы сделать его явным.Возможно, это не лучший вариант использования, но он может выглядеть примерно так:

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

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

и регистрировать его следующим образом:

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

Это скажет StructureMap передать любой универсальный параметрдля запрошенных ICalculator до Calculator ( открытых обобщений ), которые затем создают объекты стратегии в конструкторе.

В качестве альтернативы вы можете использовать маркерные интерфейсы вместогенерики, но, опять же, все зависит от вашего конкретного сценария, и, возможно, самое простое решение с самого начала подходит лучше всего.

1 голос
/ 05 июля 2011

Одним из методов является определение зависимости при получении экземпляра с использованием метода With.

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

Единственный другой способ, который я могу придумать, - это предоставить isntances в качестве аргументов конструктора при регистрации типов.Я могу привести пример завтра.

...