2013-06-17 2 views
2
interface IRecipe<T> 
{ 
    ICollection<IIngredient<T>> Ingredients { get; set; } 
    T Cook(); 
} 

interface IIngredient<T> {} 

public class Cheese : IIngredient<Pizza> {} 
public class Tomato : IIngredient<Pizza> {} 

public class Egg : IIngredient<Omlette> {} 

내가 IRecipe<SomeType>의 인스턴스를 요청할 때 StructureMap이 IIngredient<SomeType>의 모든 구현을 발견하고 어떻게 든 Recipe로 등록하는 것이 원하는 여러 일치하는 클래스를 주입.structuremap

예. IRecipe<Pizza> 인터페이스를 요청하면 올바른 재료를 가진 Recipe<Pizza>의 구체적인 인스턴스가 표시됩니다.

이것을 달성 할 방법이 있습니까?

답변

4

예이 작업은 StructureMap에서 수행 할 수 있습니다.

내가 읽기 전용 ICollection<IIngredient<T>> Ingredients을했습니다, 여기에 등록

public StructureMap.IContainer ConfigureStructureMap() 
{ 
    StructureMap.IContainer structureMap; 

    StructureMap.Configuration.DSL.Registry registry = 
     new StructureMap.Configuration.DSL.Registry(); 

    registry.Scan(scanner => 
    { 
     scanner.TheCallingAssembly(); 
     scanner.ConnectImplementationsToTypesClosing(typeof(IIngredient<>)); 
    }); 

    structureMap = new StructureMap.Container(registry); 

    structureMap.Configure(cfg => 
     cfg.For(typeof(IRecipe<>)).Use(typeof(Recipe<>))); 

    return structureMap; 
} 

방법이다 PizzaOmlette의 구체적인 구현을 추가하고 모두 Recipe

public class Pizza { } 
public class Omlette { } 

public class Recipe<T> : IRecipe<T> where T : class, new() 
{ 
    private readonly IEnumerable<IIngredient<T>> _ingredients; 
    public Recipe(IEnumerable<IIngredient<T>> ingredients) 
    { 
     _ingredients = ingredients; 
    } 
    public ICollection<IIngredient<T>> Ingredients 
    { 
     get { return _ingredients.ToList(); } 
    } 
    public T Cook() 
    { 
     return new T(); 
    } 
} 

public interface IRecipe<T> 
{ 
    ICollection<IIngredient<T>> Ingredients { get; } 
    T Cook(); 
} 

public interface IIngredient<T> { } 
public class Cheese : IIngredient<Pizza>, IIngredient<Omlette> { } 
public class Tomato : IIngredient<Pizza>, IIngredient<Omlette> { } 
public class Egg : IIngredient<Omlette> { } 

사용할 수 CheeseTomato 확장 그리고 두 가지 테스트 방법

[Test] 
public void StructureMapGetInstance_Pizza_ReturnsTwoIngredients() 
{ 
    StructureMap.IContainer structureMap = ConfigureStructureMap(); 

    var pizza = structureMap.GetInstance<IRecipe<Pizza>>(); 

    Assert.That(pizza.Ingredients.Count, Is.EqualTo(2)); 
} 

[Test] 
public void StructureMapGetInstance_Omlette_ReturnsThreeIngredients() 
{ 
    StructureMap.IContainer structureMap = ConfigureStructureMap(); 

    var omlette = structureMap.GetInstance<IRecipe<Omlette>>(); 

    Assert.That(omlette.Ingredients.Count, Is.EqualTo(3)); 
} 
+0

화려한 감사합니다. 'ConnectImplementationsToTypesClosing'과'AddAllTypesOf' 사이의 차이점을 아십니까? 그들은 둘 다 여기에서 같은 결과를 얻는 것으로 보입니다. – fearofawhackplanet

+0

'AddAllTypesOf'를 사용하면 'IIngredient '에 대한 두 번째 테스트가 하나의 성분 만 반환되어 '치즈'와 '토마토'(즉, 'IIngredient ')의 'IIngredient '의 첫 번째 정의가 등록되었습니다. 대신 ConnectImplementationsToTypesClosing을 사용하여 두 번째 테스트를 수정했습니다. – qujck