Pierre Greborio.NET

Talking about .NET world

[Money Pattern] Currencies

In the past blog I introduced the concept of Currency. It was really poor in terms of functionality since I have to set all its characteristics (symbol. name and ISO 4217 code) every time. It would be useful to have an internal table containing all currencies of the world:

internal sealed class CurrencyTable : Dictionary<string, Currency>
{
 private static volatile CurrencyTable _table;
 private static object syncRoot = new Object();

 private CurrencyTable()
 {
  this.Add("EUR", new Currency("EUR", "Euro", "\u20AC"));
  this.Add("USD", new Currency("USD", "Dollars", "\u0024"));
  this.Add("CAD", new Currency("CAD", "Dollars", "\u0024"));
  this.Add("GBP", new Currency("GBP", "Pounds", "\u00A3"));
 }

 private static CurrencyTable Table
 {
  get
  {
   if (_table == null)
   {
    lock (syncRoot)
    {
     if (_table == null)
      _table = new CurrencyTable();
    }
   }

   return _table;
  }
 }

 public static Currency GetCurrency(string isoCurrencyCode)
 {
  string key = isoCurrencyCode.ToUpper();
  if (Table.ContainsKey(key))
   return Table[key];
  else
   return new Currency();
 }
}

The the above code I made two choices:

  1. If the currency doesn't exists in the table then get the default (eur) instead of raising an KeyNotFoundException
  2. I fill the currency table from the code. I could use a resource file (better) instead. 

Now, I can add a new Currency constructor which lookups the currency from its ISO code:

public Currency(string isoCode)
{
 ISOCode = isoCode;

 Currency lookup = CurrencyTable.GetCurrency(isoCode);
 if (lookup != null)
 {
  Name = lookup.Name;
  Symbol = lookup.Symbol;
 }
}

And set two new Money constructors:

public Money(decimal amount, string isoCurrencyCode)
{
 _amount = amount;
 _currency = CurrencyTable.GetCurrency(isoCurrencyCode);
}

public Money(decimal amount, Currency currency)
{
 _amount = amount;
 _currency = currency;
}

With the last constructor I can refactor the arithmetic operators so that they consider also the currency:

public static Money operator +(Money a, Money b)
{
 CheckCurrency(a, b);
 return new Money(a._amount + b._amount, a.Currency);
}

Comments

No Comments