StructureMap: Choose concrete type of nested dependency
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(in开发者_开发百科t 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?
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.
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.
精彩评论