Skip to content

Instantly share code, notes, and snippets.

@vertonghenb
Created November 10, 2020 15:55
Show Gist options
  • Save vertonghenb/d1a00561e76f1b8fd26ae437a4887621 to your computer and use it in GitHub Desktop.
Save vertonghenb/d1a00561e76f1b8fd26ae437a4887621 to your computer and use it in GitHub Desktop.
Value Object vs Entity
public class Address : ValueObject
{
public string Street { get; init; }
public string ZipCode { get; init; }
public string Municipality { get; init; }
public string AddressLine1 => $"{Street}";
public string AddressLine2 => $"{Country.Code}-{ZipCode} {Municipality}";
/// <summary>
/// Entity Framework Core Constructor
/// </summary>
private Address() { }
public Address(string street, string zipCode, string municipalityName)
{
Street = street;
ZipCode = zipCode;
Municipality = municipalityName;
}
public Address Copy()
{
return new Address(Street, ZipCode, Municipality, Country);
}
protected override IEnumerable<object> GetAtomicValues()
{
yield return Street.ToUpper();
yield return ZipCode.ToUpper();
yield return Municipality.ToUpper();
}
}
public abstract class Entity
{
/// <summary>
/// Gets or sets the unique identifier.
/// </summary>
public int Id { get; protected set; }
/// <summary>
/// Gets or sets the created DateTime.
/// </summary>
public DateTime CreatedAt { get; set; } = DateTime.UtcNow;
/// <summary>
/// Gets or sets the updated DateTime.
/// </summary>
public DateTime UpdatedAt { get; set; } = DateTime.UtcNow;
public override bool Equals(object obj)
{
var other = obj as Entity;
// Check if the other is null.
if (other is null)
return false;
// Check if the objects refer to the same alloc. in memory.
if (ReferenceEquals(this, other))
return true;
// Check if the types of the objects are the same.
if (GetType() != other.GetType())
return false;
// Check if the objects are transient(new).
// Meaning we can not really compare these 2 entities, since the Id was not yet set.
if (Id == 0 || other.Id == 0)
return false;
// Compare Id's.
return Id == other.Id;
}
public static bool operator ==(Entity a, Entity b)
{
// Both Entities are null, so they're the same.
if (a is null && b is null)
return true;
// One if them is null which means we cannot compare.
if (a is null || b is null)
return false;
return a.Equals(b);
}
public static bool operator !=(Entity a, Entity b)
{
return !(a == b);
}
public override int GetHashCode()
{
// The type and identifier are the "Unique makers"
return (GetType().ToString() + Id).GetHashCode();
}
public override string ToString()
{
return $"{GetType().Name} - {Id}";
}
}
public abstract class ValueObject
{
protected static bool EqualOperator(ValueObject left, ValueObject right)
{
if (left is null ^ right is null)
return false;
return left is null || left.Equals(right);
}
protected static bool NotEqualOperator(ValueObject left, ValueObject right)
{
return !(EqualOperator(left, right));
}
protected abstract IEnumerable<object> GetAtomicValues();
public override bool Equals(object obj)
{
if (obj == null || obj.GetType() != GetType())
{
return false;
}
ValueObject other = (ValueObject)obj;
IEnumerator<object> thisValues = GetAtomicValues().GetEnumerator();
IEnumerator<object> otherValues = other.GetAtomicValues().GetEnumerator();
while (thisValues.MoveNext() && otherValues.MoveNext())
{
if (thisValues.Current is null ^ otherValues.Current is null)
return false;
if (thisValues.Current != null && !thisValues.Current.Equals(otherValues.Current))
return false;
}
return !thisValues.MoveNext() && !otherValues.MoveNext();
}
public override int GetHashCode()
{
return GetAtomicValues()
.Select(x => x != null ? x.GetHashCode() : 0)
.Aggregate((x, y) => x ^ y);
}
public static bool operator !=(ValueObject a, ValueObject b)
{
return !(a == b);
}
public static bool operator ==(ValueObject a, ValueObject b)
{
if (a is null && b is null)
return true;
if (a is null || b is null)
return false;
return a.Equals(b);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment