Skip to content

Instantly share code, notes, and snippets.

@1saeedsalehi
Last active April 1, 2020 12:51
Show Gist options
  • Save 1saeedsalehi/e2b454a3be06fb81a5e9f2782f316991 to your computer and use it in GitHub Desktop.
Save 1saeedsalehi/e2b454a3be06fb81a5e9f2782f316991 to your computer and use it in GitHub Desktop.
Deal with Primitive Obsession - define ValueObjects in a single line (of C#).
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