Skip to content

Instantly share code, notes, and snippets.

@NickDarvey
Created May 1, 2018 04:59
Show Gist options
  • Save NickDarvey/56bb824ff985598da916f47be63b4ef0 to your computer and use it in GitHub Desktop.
Save NickDarvey/56bb824ff985598da916f47be63b4ef0 to your computer and use it in GitHub Desktop.
using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using System.Reflection;
using System.Xml;
using System.Xml.Schema;
using System.Xml.Serialization;
namespace Thingy
{
/// <summary>
///
/// </summary>
/// <remarks>
/// Based on https://github.com/mcintyre321/ValueOf/blob/master/ValueOf/ValueOf.cs
///
/// Copyright(c) 2016 Harry McIntyre
///
/// Permission is hereby granted, free of charge, to any person obtaining a copy of this software
/// and associated documentation files (the "Software"), to deal in the Software without restriction,
/// including without limitation the rights to use, copy, modify, merge, publish, distribute,
/// sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
/// furnished to do so, subject to the following conditions:
///
/// The above copyright notice and this permission notice shall be included in all copies or
/// substantial portions of the Software.
/// </remarks>
public abstract class TypeOf<TValue, TThis>
where TThis : TypeOf<TValue, TThis>, new()
{
private static readonly Func<TThis> Factory;
private static readonly EqualityComparer<TValue> Comparer = EqualityComparer<TValue>.Default;
protected virtual (bool IsValid, string ErrorMessage) IsValid() => (true, default);
static TypeOf()
{
var ctor = typeof(TThis).GetTypeInfo().GetConstructor(new Type[0]);
Expression[] 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 Create(TValue from) =>
TryCreate(from, out var value, out var error)
? value : throw new ArgumentException(error, typeof(TThis).GetTypeInfo().Name);
public static bool TryCreate(TValue from, out TThis value) =>
TryCreate(from, out value, out var _);
public static bool TryCreate(TValue from, out TThis value, out string errorMessage)
{
if (from == null) throw new ArgumentNullException(nameof(value));
var x = Factory();
x.Value = from;
var validation = x.IsValid();
value = validation.IsValid ? x : default;
errorMessage = validation.IsValid ? default : validation.ErrorMessage;
return validation.IsValid;
}
protected bool Equals(TypeOf<TValue, TThis> other) =>
Comparer.Equals(Value, other.Value);
public override bool Equals(object obj) =>
ReferenceEquals(null, obj) ? false
: ReferenceEquals(this, obj) ? true
: obj.GetType() != this.GetType() ? false
: Equals((TypeOf<TValue, TThis>)obj);
public override int GetHashCode() =>
Comparer.GetHashCode(Value);
public static bool operator ==(TypeOf<TValue, TThis> a, TypeOf<TValue, TThis> b) =>
ReferenceEquals(a, null) && ReferenceEquals(b, null) ? true
: ReferenceEquals(a, null) || ReferenceEquals(b, null) ? false
: a.Equals(b);
public static bool operator !=(TypeOf<TValue, TThis> a, TypeOf<TValue, TThis> b) =>
!(a == b);
public override string ToString() =>
Value?.ToString();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment