using System.Collections.Generic;
using static System.Console;
static IUnityContainer unityContainer = new UnityContainer();
private static void RegisterTypes()
unityContainer.RegisterType<IWingFactory, WingFactory>();
public static void Main()
var wingFactory = unityContainer.Resolve<WingFactory>();
var order = new Order(wingFactory);
var chicken = order.WingFactory.Create<Chicken>();
var cauliflower = order.WingFactory.Create<Cauliflower>();
var tofu = order.WingFactory.Create<Tofu>();
order.Items.Add(chicken);
order.Items.Add(cauliflower);
public IWingFactory WingFactory
public Order(IWingFactory wingFactory)
this.WingFactory = wingFactory;
this.Items = new List<Item>();
public virtual string Name
public override string ToString()
return $"{nameof(Name)}: {Name}";
public class Chicken : Item
public override string Name => "Chicken";
public class Cauliflower : Item
public override string Name => "Cauliflower";
public override string Name => "Tofu";
public interface IWingFactory
private static readonly string WingCooker = "WingCooker";
WingType Create<WingType>()
where WingType : Item, new()
dynamic wingCooker = Activator.CreateInstance(Type.GetType(typeof(WingType).Name + WingCooker), new WingType());
return wingCooker.Cook().Item;
public class WingFactory : IWingFactory
public abstract class WingCooker<WingType>
where WingType : Item, new()
public WingCooker(WingType item)
public WingCooker<WingType> Wash()
WriteLine($"Washing the {Item.Name} wings thoroughly.");
public WingCooker<WingType> Season()
WriteLine($"Seasoning the {Item.Name} wings generously.");
public WingCooker<WingType> PutInBasket()
WriteLine($"Putting the {Item.Name} wings into the frying basket carefully.");
public WingCooker<WingType> PutOnBakingTray()
WriteLine($"Putting the {Item.Name} wings onto the baking tray carefully.");
public WingCooker<WingType> PlaceInOven()
WriteLine($"Placing the {Item.Name} wings into the oven.");
public WingCooker<WingType> DropInVAT()
WriteLine($"Dropping the frying basket full of the {Item.Name} wings in deep fry VAT.");
public WingCooker<WingType> SetTimer()
WriteLine($"Setting the timer for the {Item.Name} wings.");
public WingCooker<WingType> PressOutWater()
WriteLine($"Pressing out the water for the {Item.Name} wings.");
public WingCooker<WingType> CutIntoRectangles()
WriteLine($"Cutting out block of {Item.Name} into evenly shaped rectangles for the {Item.Name} wings.");
public WingCooker<WingType> Remove()
WriteLine($"Removing the {Item.Name} wings.");
public WingCooker<WingType> Package()
WriteLine($"Packaging the {Item.Name} wings.");
public abstract WingCooker<WingType> Cook();
public class ChickenWingCooker : WingCooker<Chicken>
public ChickenWingCooker(Chicken item): base(item)
public override WingCooker<Chicken> Cook()
return this.Wash().Season().PutInBasket().DropInVAT().SetTimer().Remove().Package();
public class CauliflowerWingCooker : WingCooker<Cauliflower>
public CauliflowerWingCooker(Cauliflower item): base(item)
public override WingCooker<Cauliflower> Cook()
return this.Wash().Season().PutOnBakingTray().PlaceInOven().SetTimer().Remove().Package();
public class TofuWingCooker : WingCooker<Tofu>
public TofuWingCooker(Tofu item): base(item)
public override WingCooker<Tofu> Cook()
return this.Wash().PressOutWater().CutIntoRectangles().Season().SetTimer().Remove().Package();