Created
March 21, 2014 11:08
-
-
Save svenschelfaut/9683950 to your computer and use it in GitHub Desktop.
Using value objects with external services. Is this a good method?
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
namespace MoneyTest | |
{ | |
public static class Program | |
{ | |
static void Main(string[] args) | |
{ | |
var twentyEuro = 20.0.Euro(); | |
var twentyDollar = 20.0.Dollar(); | |
var converter = new MoneyConverter(new ExchangeRateService()); | |
var twentyDollarInEuro = converter.Convert(twentyDollar, Currency.EUR); | |
Console.WriteLine("20 USD in euro: " + twentyDollarInEuro); | |
var sum = twentyEuro + twentyDollarInEuro; | |
Console.WriteLine("Result 20 EUR + 20 USD: " + sum); | |
Console.ReadLine(); | |
} | |
} | |
public enum Currency | |
{ | |
USD, | |
EUR | |
} | |
public sealed class MoneyConverter | |
{ | |
private readonly IDetermineExchangeRate _exchangeRateService; | |
public MoneyConverter(IDetermineExchangeRate exchangeRateService) | |
{ | |
_exchangeRateService = exchangeRateService; | |
} | |
public Money Convert(Money money, Currency toCurrency) | |
{ | |
var exchangeRate = _exchangeRateService.DetermineExchangeRate(money.Currency, toCurrency); | |
return new Money(exchangeRate * money.Amount, toCurrency); | |
} | |
} | |
public interface IDetermineExchangeRate | |
{ | |
double DetermineExchangeRate(Currency fromCurrency, Currency toCurrency); | |
} | |
public class ExchangeRateService : IDetermineExchangeRate | |
{ | |
public double DetermineExchangeRate(Currency fromCurrency, Currency toCurrency) | |
{ | |
if (fromCurrency == toCurrency) | |
return 1; | |
if (fromCurrency == Currency.EUR && toCurrency == Currency.USD) | |
return 1.37; | |
if (fromCurrency == Currency.USD && toCurrency == Currency.EUR) | |
return 0.72; | |
throw new ArgumentException(string.Format("No exchange rate available for {0} to {1}", fromCurrency, toCurrency)); | |
} | |
} | |
public sealed class Money | |
{ | |
public double Amount { get; private set; } | |
public Currency Currency { get; private set; } | |
public Money(double amount, Currency currency) | |
{ | |
Amount = amount; | |
Currency = currency; | |
} | |
public static Money operator +(Money money1, Money money2) | |
{ | |
CheckThatCurrenciesAreTheSame(money1, money2); | |
return new Money(money1.Amount + money2.Amount, money1.Currency); | |
} | |
public static Money operator -(Money money1, Money money2) | |
{ | |
CheckThatCurrenciesAreTheSame(money1, money2); | |
return new Money(money1.Amount - money2.Amount, money1.Currency); | |
} | |
private static void CheckThatCurrenciesAreTheSame(Money money1, Money money2) | |
{ | |
if (money1.Currency != money2.Currency) | |
{ | |
throw new ArgumentException( | |
string.Format("Can't add {0} to {1}", money2.Currency, money1.Currency)); | |
} | |
} | |
private bool Equals(Money other) | |
{ | |
return Amount.Equals(other.Amount) && Currency == other.Currency; | |
} | |
public override bool Equals(object obj) | |
{ | |
if (ReferenceEquals(null, obj)) return false; | |
if (ReferenceEquals(this, obj)) return true; | |
if (obj.GetType() != GetType()) return false; | |
return Equals((Money)obj); | |
} | |
public override int GetHashCode() | |
{ | |
unchecked | |
{ | |
return (Amount.GetHashCode() * 397) ^ (int)Currency; | |
} | |
} | |
public override string ToString() | |
{ | |
return string.Format("{0} {1}", Amount, Currency); | |
} | |
} | |
public static class MoneyExtensions | |
{ | |
public static Money Euro(this double amount) | |
{ | |
return new Money(amount, Currency.EUR); | |
} | |
public static Money Dollar(this double amount) | |
{ | |
return new Money(amount, Currency.USD); | |
} | |
} | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment