The Bitter Coder Tutorials, Binsor Style: Injecting Service Arrays

Mon, Oct 6, 2008 3-minute read

Previous posts in the series:

This post feeds off off Part 12 and is based on Alex’s post here.  We are going to rework the last post and remove the decorator pattern.  Instead, we’ll create a calculator that manages any number of other calculators, which are injected as an array.

So, in keeping with my shameless plagirizing of Alex’s code, here is the abstract class for our new calculators:

namespace BitterCoder.Tutorials.Binsor.Core

{

public abstract class AbstractCalculator

{

public abstract decimal Calculate(decimal currentTotal, Order order);

}

}

And now our total calculator:

using System.Linq;

 

namespace BitterCoder.Tutorials.Binsor.Core

{

public class TotalCalculator : AbstractCalculator

{

private static decimal CalculateTotal(Order order)

{

return order.Items.Sum(item => item.CostPerItem*item.Quantity);

}

 

public override decimal Calculate(decimal currentTotal, Order order)

{

return currentTotal + CalculateTotal(order);

}

}

}

And the GST calculator:

namespace BitterCoder.Tutorials.Binsor.Core

{

public class GSTCostCalculatorNoDecorator : AbstractCalculator

{

private decimal _gstRate = 1.125m;

 

public decimal GstRate

{

get { return _gstRate; }

set { _gstRate = value; }

}

 

private static bool IsNewZealand(Order order)

{

return (order.CountryCode == "NZ");

}

 

public override decimal Calculate(decimal currentTotal, Order order)

{

if (IsNewZealand(order))

{

return (currentTotal*_gstRate);

}

return currentTotal;

}

}

}

The shipping calculator:

namespace BitterCoder.Tutorials.Binsor.Core

{

public class ShippingCalculatorNoDecorator : AbstractCalculator

{

private decimal _fragileShippingPremium = 1.5m;

private decimal _shippingCost = 5.0m;

 

public decimal ShippingCost

{

get { return _shippingCost; }

set { _shippingCost = value; }

}

 

public decimal FragileShippingPremium

{

get { return _fragileShippingPremium; }

set { _fragileShippingPremium = value; }

}

 

private decimal GetShippingTotal(Order order)

{

decimal shippingTotal = 0;

return order.Items.Sum(item =>

{

decimal itemShippingCost = ShippingCost*item.Quantity;

if (item.IsFragile) itemShippingCost *= FragileShippingPremium;

return shippingTotal += itemShippingCost;

});

}

 

public override decimal Calculate(decimal currentTotal, Order order)

{

return currentTotal + GetShippingTotal(order);

}

}

}

Lastly, our calculator of calculators, the reworked DefaultCalculator:

public class DefaultCalculatorNoDecorator : ICostCalculator

{

private readonly AbstractCalculator[] _calculators;

 

public DefaultCalculatorNoDecorator(AbstractCalculator[] _calculators)

{

this._calculators = _calculators;

}

 

 

public decimal CalculateTotal(Order order)

{

decimal currentTotal = 0;

 

return _calculators.Sum(calc => calc.Calculate(currentTotal, order));

}

}

 

So, we'll inject an array of calculators (total, shipping, and gst) into our default calculator. Binsor, away!
component "default.calculator", ICostCalculator,DefaultCalculatorNoDecorator:
    _calculators=[@total.calculatornodec,@shipping.calculatornodec,@gst.calculatornodec]

component "total.calculatornodec", AbstractCalculator,TotalCalculator

component "gst.calculatornodec", AbstractCalculator, GSTCostCalculatorNoDecorator:
    GstRate=Convert.ToDecimal(1.20)

component "shipping.calculatornodec", AbstractCalculator, ShippingCalculatorNoDecorator:
    FragileShippingPremium=Convert.ToDecimal(0.0)
Just like we did in our post on arrays, we inject an array of dependencies.  Changing the order is just a matter of switching the order in the binsor.  All good. Running the program gives the same output as the last post. Next post, which is the last in the series until Alex writes more (whew), is on the "Startable" facility.
Reblog this post [with Zemanta]