Skip to content

Instantly share code, notes, and snippets.

@CumpsD
Created November 21, 2017 19:50
Show Gist options
  • Save CumpsD/e3ddb20262f4290997aa8aea7c6691b4 to your computer and use it in GitHub Desktop.
Save CumpsD/e3ddb20262f4290997aa8aea7c6691b4 to your computer and use it in GitHub Desktop.
Value Objects Plumbing
namespace ValueObjects
{
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
public abstract class GuidValueObject<T> : DataTypeValueObject<T, Guid> where T : GuidValueObject<T>
{
protected GuidValueObject(Guid id) : base(id) { }
}
public abstract class DateTimeValueObject<T> : DataTypeValueObject<T, DateTime> where T : DateTimeValueObject<T>
{
protected DateTimeValueObject(DateTime date) : base(date) { }
}
public abstract class StringValueObject<T> : DataTypeValueObject<T, string> where T : StringValueObject<T>
{
protected StringValueObject(string @string) : base(@string) { }
}
public abstract class IntValueObject<T> : DataTypeValueObject<T, int> where T : IntValueObject<T>
{
protected IntValueObject(int number) : base(number) { }
}
public abstract class ByteArrayValueObject<T> : DataTypeValueObject<T, byte[]> where T : ByteArrayValueObject<T>
{
public ImmutableArray<byte> ImmutableBytes => Value.ToImmutableArray();
protected ByteArrayValueObject(byte[] bytes) : base(bytes) { }
}
public abstract class DataTypeValueObject<T, TDataType> : ValueObject<T> where T : ValueObject<T>
{
protected TDataType Value { get; }
protected DataTypeValueObject(TDataType number) => Value = number;
public static implicit operator TDataType(DataTypeValueObject<T, TDataType> valueObject) => valueObject.Value;
protected override IEnumerable<object> Reflect()
{
yield return Value;
}
}
// https://smellegantcode.wordpress.com/2009/06/09/generic-value-object-with-yield-return/
public abstract class ValueObject<T> : IEquatable<T> where T : ValueObject<T>
{
protected abstract IEnumerable<object> Reflect();
public static bool operator ==(ValueObject<T> obj1, ValueObject<T> obj2)
{
if (ReferenceEquals(obj1, obj2))
return true;
if (ReferenceEquals(obj1, null))
return false;
if (ReferenceEquals(obj2, null))
return false;
return obj1.Equals(obj2);
}
public static bool operator !=(ValueObject<T> obj1, ValueObject<T> obj2) => !(obj1 == obj2);
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(obj as T);
}
public bool Equals(T other)
{
if (ReferenceEquals(null, other))
return false;
if (ReferenceEquals(this, other))
return true;
return Reflect().SequenceEqual(other.Reflect());
}
public override int GetHashCode()
{
int HashCodeAggregator(int hashCode, object value) => value == null
? hashCode
: hashCode ^ value.GetHashCode();
return Reflect().Aggregate(36, HashCodeAggregator);
}
public override string ToString()
{
object StringAggregator(object l, object r) => $"{l}, {r}";
return Reflect().Aggregate(StringAggregator).ToString();
//return $"{{ {Reflect().Aggregate(StringAggregator)} }}";
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment