Reputation: 53446
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> {}
I want that when I request an instance of IRecipe<SomeType>
StructureMap finds all implementations of IIngredient<SomeType>
and registers them with Recipe
somehow.
So e.g. if I request interface IRecipe<Pizza>
I will get concrete instance of Recipe<Pizza>
that has the correct ingredients.
Is there any way to achieve this?
Upvotes: 2
Views: 749
Reputation: 14578
Yes this can be done with StructureMap.
I've made ICollection<IIngredient<T>> Ingredients
readonly, added concrete implementations of Pizza
and Omlette
and extended Cheese
and Tomato
to be available for both Recipe
's
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> { }
Here's the method for registration
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;
}
And two test methods
[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));
}
Upvotes: 4