Create a gist now

Instantly share code, notes, and snippets.

@vkhorikov /1.cs
Last active Mar 8, 2018

Embed
What would you like to do?
Value Object
public abstract class ValueObject<T>
where T : ValueObject<T>
{
public override bool Equals(object obj)
{
var valueObject = obj as T;
if (ReferenceEquals(valueObject, null))
return false;
if (GetType() != obj.GetType())
return false;
return EqualsCore(valueObject);
}
protected abstract bool EqualsCore(T other);
public override int GetHashCode()
{
return GetHashCodeCore();
}
protected abstract int GetHashCodeCore();
public static bool operator ==(ValueObject<T> a, ValueObject<T> b)
{
if (ReferenceEquals(a, null) && ReferenceEquals(b, null))
return true;
if (ReferenceEquals(a, null) || ReferenceEquals(b, null))
return false;
return a.Equals(b);
}
public static bool operator !=(ValueObject<T> a, ValueObject<T> b)
{
return !(a == b);
}
}
public class Address : ValueObject<Address>
{
public string Street { get; }
public string City { get; }
public string ZipCode { get; }
public Address(string street, string city, string zipCode)
{
Street = street;
City = city;
ZipCode = zipCode;
}
protected override bool EqualsCore(Address other)
{
return Street == other.Street
&& City == other.City
&& ZipCode == other.ZipCode;
}
protected override int GetHashCodeCore()
{
unchecked
{
int hashCode = Street.GetHashCode();
hashCode = (hashCode * 397) ^ City.GetHashCode();
hashCode = (hashCode * 397) ^ ZipCode.GetHashCode();
return hashCode;
}
}
}
public abstract class ValueObject
{
protected abstract IEnumerable<object> GetEqualityComponents();
public override bool Equals(object obj)
{
if (obj == null)
return false;
if (GetType() != obj.GetType())
throw new ArgumentException($"Invalid comparison of Value Objects of different types: {GetType()} and {obj.GetType()}");
var valueObject = (ValueObject)obj;
return GetEqualityComponents().SequenceEqual(valueObject.GetEqualityComponents());
}
public override int GetHashCode()
{
return GetEqualityComponents()
.Aggregate(1, (current, obj) =>
{
unchecked
{
return current * 23 + (obj?.GetHashCode() ?? 0);
}
});
}
public static bool operator ==(ValueObject a, ValueObject b)
{
if (ReferenceEquals(a, null) && ReferenceEquals(b, null))
return true;
if (ReferenceEquals(a, null) || ReferenceEquals(b, null))
return false;
return a.Equals(b);
}
public static bool operator !=(ValueObject a, ValueObject b)
{
return !(a == b);
}
}
public class Address : ValueObject
{
public string Street { get; }
public string City { get; }
public string ZipCode { get; }
public Address(string street, string city, string zipCode)
{
Street = street;
City = city;
ZipCode = zipCode;
}
protected override IEnumerable<object> GetEqualityComponents()
{
yield return Street;
yield return City;
yield return ZipCode;
}
}
protected override IEnumerable<object> GetEqualityComponents()
{
yield return Street;
yield return City;
yield return ZipCode;
}
public class Address : ValueObject
{
public string Street { get; }
public string City { get; }
public string ZipCode { get; }
public List<Tenant> Tenants { get; }
public Address(string street, string city, string zipCode, List<Tenant> tenants)
{
Street = street;
City = city;
ZipCode = zipCode;
Tenants = tenants;
}
protected override IEnumerable<object> GetEqualityComponents()
{
yield return Street;
yield return City;
yield return ZipCode;
foreach (Tenant tenant in Tenants)
{
yield return tenant;
}
}
}
public class Money : ValueObject
{
public string Currency { get; }
public decimal Amount { get; }
public Money(string currency, decimal amount)
{
Currency = currency;
Amount = amount;
}
protected override IEnumerable<object> GetEqualityComponents()
{
yield return Currency.ToUpper();
yield return Math.Round(Amount, 2);
}
}
var money1 = new Money("usd", 2.2222m);
var money2 = new Money("USD", 2.22m);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment