Last active
April 1, 2020 12:51
-
-
Save 1saeedsalehi/e2b454a3be06fb81a5e9f2782f316991 to your computer and use it in GitHub Desktop.
Deal with Primitive Obsession - define ValueObjects in a single line (of C#).
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; | |
using System.Collections.Generic; | |
using System.Linq; | |
using System.Linq.Expressions; | |
using System.Reflection; | |
namespace ValueOf | |
{ | |
public class ValueOf<TValue, TThis> where TThis : ValueOf<TValue, TThis>, new() | |
{ | |
private static readonly Func<TThis> Factory; | |
/// <summary> | |
/// WARNING - THIS FEATURE IS EXPERIMENTAL. I may change it to do | |
/// validation in a different way. | |
/// Right now, override this method, and throw any exceptions you need to. | |
/// Access this.Value to check the value | |
/// </summary> | |
protected virtual void Validate() | |
{ | |
} | |
static ValueOf() | |
{ | |
ConstructorInfo ctor = typeof(TThis) | |
.GetTypeInfo() | |
.DeclaredConstructors | |
.First(); | |
var argsExp = new Expression[0]; | |
NewExpression newExp = Expression.New(ctor, argsExp); | |
LambdaExpression lambda = Expression.Lambda(typeof(Func<TThis>), newExp); | |
Factory = (Func<TThis>)lambda.Compile(); | |
} | |
public TValue Value { get; protected set; } | |
public static TThis From(TValue item) | |
{ | |
TThis x = Factory(); | |
x.Value = item; | |
x.Validate(); | |
return x; | |
} | |
protected virtual bool Equals(ValueOf<TValue, TThis> other) | |
{ | |
return EqualityComparer<TValue>.Default.Equals(Value, other.Value); | |
} | |
public override bool Equals(object obj) | |
{ | |
if (obj is null) | |
return false; | |
if (ReferenceEquals(this, obj)) | |
return true; | |
return obj.GetType() == GetType() && Equals((ValueOf<TValue, TThis>)obj); | |
} | |
public override int GetHashCode() | |
{ | |
return EqualityComparer<TValue>.Default.GetHashCode(Value); | |
} | |
public static bool operator ==(ValueOf<TValue, TThis> a, ValueOf<TValue, TThis> b) | |
{ | |
if (a is null && b is null) | |
return true; | |
if (a is null || b is null) | |
return false; | |
return a.Equals(b); | |
} | |
public static bool operator !=(ValueOf<TValue, TThis> a, ValueOf<TValue, TThis> b) | |
{ | |
return !(a == b); | |
} | |
public override string ToString() | |
{ | |
return Value.ToString(); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment