StructureMap: выберите конкретный тип вложенной зависимости
Калькуляторы:
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 ответа
Попробуйте вот так:
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
( open generics), который затем создает объекты стратегии в конструкторе.
В качестве альтернативы вы можете использовать маркерные интерфейсы вместо универсальных, но, опять же, все зависит от вашего конкретного сценария, и, возможно, самое простое решение с самого начала подходит лучше всего.
Одним из методов является определение зависимости при получении экземпляра с использованием With
метод.
var additionStrategy = ObjectFactory
.GetNamedInstance<ICalculatorStrategy>("Addition");
var c1 = ObjectFactory.With(additionStrategy).GetInstance<CalculatorUsageOne>();
Единственный другой способ, который я могу придумать, - предоставить isntances в качестве аргументов конструктора при регистрации типов. Я могу привести пример завтра.