-
Notifications
You must be signed in to change notification settings - Fork 1
/
Money.cs
89 lines (67 loc) · 2.9 KB
/
Money.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
using Domain.Common;
namespace Domain.ValueObjects;
public class Money : ValueObject
{
public decimal Amount { get; set; }
public Currency Currency { get; set; }
public Money(decimal amount, Currency currency)
{
this.Amount = amount;
this.Currency = currency;
}
public static Money operator +(Money left, Money right)
{
if (left.Currency != right.Currency)
{
throw new InvalidOperationException("Currencies have to be equal.");
}
return new Money(left.Amount + right.Amount, left.Currency);
}
public static Money operator -(Money left, Money right)
{
if (left.Currency != right.Currency)
{
throw new InvalidOperationException("Currencies have to be equal.");
}
if (left < right)
{
throw new InvalidOperationException("Not enough funds.");
}
return new Money(left.Amount - right.Amount, left.Currency);
}
public static Money operator *(Money amount, decimal factor) =>
new(amount.Amount * factor, amount.Currency);
public static Money operator *(decimal factor, Money amount) =>
new(amount.Amount * factor, amount.Currency);
public static Money operator /(Money amount, decimal factor) =>
new(amount.Amount / factor, amount.Currency);
public static decimal operator /(Money a, Money b) =>
a.Currency == b.Currency ? a.Amount / b.Amount
: RaiseCurrencyError<decimal>("divide", a, b);
public static bool operator >(Money left, Money right) =>
left.Currency == right.Currency ? left.Amount > right.Amount
: RaiseCurrencyComparisonError(left, right);
public static bool operator <(Money left, Money right) =>
left.Currency == right.Currency ? left.Amount < right.Amount
: RaiseCurrencyComparisonError(left, right);
public static bool operator >=(Money left, Money right) =>
left.Currency == right.Currency ? left.Amount >= right.Amount
: RaiseCurrencyComparisonError(left, right);
public static bool operator <=(Money left, Money right) =>
left.Currency == right.Currency ? left.Amount <= right.Amount
: RaiseCurrencyComparisonError(left, right);
public static implicit operator decimal(Money a) =>
a.Amount;
private static bool RaiseCurrencyComparisonError(Money a, Money b) =>
RaiseCurrencyError<bool>("compare", a, b);
private static T RaiseCurrencyError<T>(string operation, Money a, Money b) =>
throw new ArgumentException($"Cannot {operation} {a.Currency} and {b.Currency}");
public static Money Zero() => new(0, Currency.None);
public static Money Zero(Currency currency) => new(0, currency);
public bool IsZero() => this == Zero();
protected override IEnumerable<object> GetEqualityComponents()
{
yield return Amount;
yield return Currency;
}
}