public class Order
{
private string _countryCode;
private readonly List<OrderItem> _items = new List<OrderItem>();
public List<OrderItem> Items
get { return _items; }
}
public string CountryCode
get { return _countryCode; }
set { _countryCode = value; }
public class OrderItem
private string _name;
private bool _isFragile;
private int _quantity;
private decimal _costPerItem;
public OrderItem(string name, int quantity, decimal costPerItem, bool isFragile)
_name = name;
_quantity = quantity;
_costPerItem = costPerItem;
_isFragile = isFragile;
public bool IsFragile
get { return _isFragile; }
set { _isFragile = value; }
public int Quantity
get { return _quantity; }
set { _quantity = value; }
public decimal CostPerItem
get { return _costPerItem; }
set { _costPerItem = value; }
public string Name
get { return _name; }
set { _name = value; }
public interface ICostCalculator
decimal CalculateTotal(Order order);
public class DefaultCostCalculator : ICostCalculator
public decimal CalculateTotal(Order order)
decimal total = 0;
foreach (OrderItem item in order.Items)
total += (item.Quantity*item.CostPerItem);
return total;
internal class Program
private static void Main(string[] args)
WindsorContainer container = new WindsorContainer(new XmlInterpreter());
Order order1 = new Order();
order1.CountryCode = "NZ";
order1.Items.Add(new OrderItem("water", 10, 1.0m, false));
order1.Items.Add(new OrderItem("glass", 5, 20.0m, true));
Order order2 = new Order();
order2.CountryCode = "US";
order2.Items.Add(new OrderItem("sand", 50, 0.2m, false));
ICostCalculator costCalculator = container.Resolve<ICostCalculator>();
Console.WriteLine("Cost to deliver Order 1: {0}", costCalculator.CalculateTotal(order1));
Console.WriteLine("Cost to deliver Order 2: {0}", costCalculator.CalculateTotal(order2));
Console.Read();
<component id="costCalculator.default"
service="IoC.Tutorials.Part12.ICostCalculator, IoC.Tutorials.Part12"
type="IoC.Tutorials.Part12.DefaultCostCalculator, IoC.Tutorials.Part12" />
public class GstCostCalcualtorDecoarator : ICostCalculator
private readonly ICostCalculator _innerCalculator;
private decimal _gstRate = 1.125m;
public GstCostCalcualtorDecoarator(ICostCalculator innerCalculator)
_innerCalculator = innerCalculator;
public decimal GstRate
get { return _gstRate; }
set { _gstRate = value; }
private bool IsNewZealand(Order order)
return (order.CountryCode == "NZ");
decimal innerTotal = _innerCalculator.CalculateTotal(order);
if (IsNewZealand(order))
innerTotal = (innerTotal*_gstRate);
return innerTotal;
<configuration>
<configSections>
<section name="castle"
type="Castle.Windsor.Configuration.AppDomain.CastleSectionHandler, Castle.Windsor" />
</configSections>
<castle>
<components>
<component id="costCalculator.gstDecorator"
type="IoC.Tutorials.Part12.GstCostCalcualtorDecoarator, IoC.Tutorials.Part12">
<parameters>
<innerCalculator>${costCalculator.default}</innerCalculator>
</parameters>
</component>
</components>
</castle>
</configuration>
public class ShippingCostCalculatorDecorator : ICostCalculator
private decimal _shippingCost = 5.0m;
private decimal _fragileShippingPremium = 1.5m;
public ShippingCostCalculatorDecorator(ICostCalculator innerCalculator)
public decimal ShippingCost
get { return _shippingCost; }
set { _shippingCost = value; }
public decimal FragileShippingPremium
get { return _fragileShippingPremium; }
set { _fragileShippingPremium = value; }
return innerTotal + GetShippingTotal(order);
private decimal GetShippingTotal(Order order)
decimal shippingTotal = 0;
decimal itemShippingCost = ShippingCost*item.Quantity;
if (item.IsFragile) itemShippingCost *= FragileShippingPremium;
shippingTotal += itemShippingCost;
return shippingTotal;
<component id="costCalculator.shippingDecorator"
type="IoC.Tutorials.Part12.ShippingCostCalculatorDecorator, IoC.Tutorials.Part12">
<innerCalculator>${costCalculator.gstDecorator}</innerCalculator>
<innerCalculator>${costCalculator.shippingDecorator}</innerCalculator>
<GstRate>1.20</GstRate> <!-- GST is now 20% -->
<FragileShippingPremium>0.0</FragileShippingPremium> <!-- No fragile goods premium any more-->