StructureMap: scegli il tipo concreto di dipendenza nidificata

Calcolatrici:

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

Spiegazioni del calcolatore:

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

Usi del calcolatore:

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

Registro delle mappe strutturali:

 public class DependencyRegistry : Registry { public DependencyRegistry() { For().Use().Named("Addition"); For().Use().Named("Multiply"); For().Use(); } } 

Per CalculatorUsageOne voglio aggiungere i numeri (usa AdditionCalculator ). Per CalculatorUsageTwo voglio moltiplicare i numeri (usa MultiplyCalculator ).

Come ottengo ciò con StructureMap?

Prova così:

 For().Use() .Ctor().Is( x => x.Ctor().Is() ); For().Use() .Ctor().Is( x => x.Ctor().Is() ); 

È ansible nidificare le configurazioni del grafico degli oggetti nel modo più approfondito necessario. Ad ogni modo, penserei di usare i generici qui per mostrare le dipendenze in modo più esplicito.

modifica di generici:

Se usare i generici è una buona idea, dipende dal tuo scenario. Se non hai specificato le dipendenze concrete per i tuoi CalculatorUsages proposito e questo è il tuo objective per renderlo indipendente dalla strategia, la tua soluzione sembra essere la migliore.

Ma se hai solo bisogno di un’implementazione comune di Calculator in “middle layer”, puoi specificare la dipendenza di Calculator dal parametro generico per renderla esplicita. Forse non è il caso d’uso migliore qui, ma può andare in qualche modo in questo modo:

 public class CalculatorUsageOne { public CalculatorUsageOne(ICalculator calculator) { // ... } } public class Calculator where T : ICalculatorStrategy { public Calculator(T strategy) { // ... } } 

e registralo in questo modo:

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

Questo dirà a StructureMap di passare qualsiasi parametro generico per ICalculator richiesto a Calculator ( generici aperti ), che quindi istanzia gli oggetti di strategia nel costruttore.

In alternativa, puoi utilizzare le interfacce marcatore invece dei generici, ma ancora una volta tutto dipende dal tuo scenario particolare e potrebbe essere che la soluzione più semplice fin dall’inizio si adatti meglio.

Un metodo consiste nel definire la dipendenza quando si ottiene un’istanza utilizzando il metodo With .

 var additionStrategy = ObjectFactory .GetNamedInstance("Addition"); var c1 = ObjectFactory.With(additionStrategy).GetInstance(); 

L’unico altro modo in cui posso pensare è fornire le isntances come argomenti del costruttore durante la registrazione dei tipi. Posso dare un esempio domani.