Skip to content

Instantly share code, notes, and snippets.

@mowensoft
Last active October 8, 2015 01:35
Show Gist options
  • Save mowensoft/6485e6b37601d97a52c9 to your computer and use it in GitHub Desktop.
Save mowensoft/6485e6b37601d97a52c9 to your computer and use it in GitHub Desktop.
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
namespace EnsureThat
{
public static class Ensure
{
#region That method
[DebuggerStepThrough]
public static Param<T> That<T>(T value, string name = Param.DefaultName)
{
return new Param<T>(value, name);
}
[DebuggerStepThrough]
public static TypeParam ThatTypeFor<T>(T value, string name = Param.DefaultName)
{
return new TypeParam(name, value.GetType());
}
#endregion
#region Bool Extensions
[DebuggerStepThrough]
public static Param<bool> IsTrue(this Param<bool> param)
{
if (!param.Value)
{
throw CreateForParameterValidation(param, ExceptionMessages.IsNotTrue);
}
return param;
}
[DebuggerStepThrough]
public static Param<bool> IsFalse(this Param<bool> param)
{
if (param.Value)
{
throw CreateForParameterValidation(param, ExceptionMessages.IsNotFalse);
}
return param;
}
#endregion
#region Collection Extensions
[DebuggerStepThrough]
public static Param<T> HasItems<T>(this Param<T> param) where T : class, ICollection
{
if (param.Value == null || param.Value.Count < 1)
{
throw CreateForParameterValidation(param, ExceptionMessages.IsEmptyCollection);
}
return param;
}
[DebuggerStepThrough]
public static Param<Collection<T>> HasItems<T>(this Param<Collection<T>> param)
{
if (param.Value == null || param.Value.Count < 1)
{
throw CreateForParameterValidation(param, ExceptionMessages.IsEmptyCollection);
}
return param;
}
[DebuggerStepThrough]
public static Param<ICollection<T>> HasItems<T>(this Param<ICollection<T>> param)
{
if (param.Value == null || param.Value.Count < 1)
{
throw CreateForParameterValidation(param, ExceptionMessages.IsEmptyCollection);
}
return param;
}
[DebuggerStepThrough]
public static Param<T[]> HasItems<T>(this Param<T[]> param)
{
if (param.Value == null || param.Value.Length < 1)
{
throw CreateForParameterValidation(param, ExceptionMessages.IsEmptyCollection);
}
return param;
}
[DebuggerStepThrough]
public static Param<List<T>> HasItems<T>(this Param<List<T>> param)
{
if (param.Value == null || param.Value.Count < 1)
{
throw CreateForParameterValidation(param, ExceptionMessages.IsEmptyCollection);
}
return param;
}
[DebuggerStepThrough]
public static Param<IList<T>> HasItems<T>(this Param<IList<T>> param)
{
if (param.Value == null || param.Value.Count < 1)
{
throw CreateForParameterValidation(param, ExceptionMessages.IsEmptyCollection);
}
return param;
}
[DebuggerStepThrough]
public static Param<IDictionary<TKey, TValue>> HasItems<TKey, TValue>(this Param<IDictionary<TKey, TValue>> param)
{
if (param.Value == null || param.Value.Count < 1)
{
throw CreateForParameterValidation(param, ExceptionMessages.IsEmptyCollection);
}
return param;
}
[DebuggerStepThrough]
public static Param<T[]> SizeIs<T>(this Param<T[]> param, int expectedSize)
{
if (param.Value.Length != expectedSize)
{
throw CreateForParameterValidation(param, ExceptionMessages.SizeIsWrong.Inject(expectedSize));
}
return param;
}
[DebuggerStepThrough]
public static Param<IList<T>> SizeIs<T>(this Param<IList<T>> param, int expectedSize)
{
if (param.Value.Count != expectedSize)
{
throw CreateForParameterValidation(param, ExceptionMessages.SizeIsWrong.Inject(expectedSize));
}
return param;
}
[DebuggerStepThrough]
public static Param<List<T>> SizeIs<T>(this Param<List<T>> param, int expectedSize)
{
if (param.Value.Count != expectedSize)
{
throw CreateForParameterValidation(param, ExceptionMessages.SizeIsWrong.Inject(expectedSize));
}
return param;
}
[DebuggerStepThrough]
public static Param<ICollection<T>> SizeIs<T>(this Param<ICollection<T>> param, int expectedSize)
{
if (param.Value.Count != expectedSize)
{
throw CreateForParameterValidation(param, ExceptionMessages.SizeIsWrong.Inject(expectedSize));
}
return param;
}
[DebuggerStepThrough]
public static Param<Collection<T>> SizeIs<T>(this Param<Collection<T>> param, int expectedSize)
{
if (param.Value.Count != expectedSize)
{
throw CreateForParameterValidation(param, ExceptionMessages.SizeIsWrong.Inject(expectedSize));
}
return param;
}
[DebuggerStepThrough]
public static Param<IDictionary<TKey, TValue>> ContainsKey<TKey, TValue>(this Param<IDictionary<TKey, TValue>> param, TKey key)
{
if (!param.Value.ContainsKey(key))
{
throw CreateForParameterValidation(param, ExceptionMessages.ContainsKey.Inject(key));
}
return param;
}
[DebuggerStepThrough]
public static Param<Dictionary<TKey, TValue>> ContainsKey<TKey, TValue>(this Param<Dictionary<TKey, TValue>> param, TKey key)
{
if (!param.Value.ContainsKey(key))
{
throw CreateForParameterValidation(param, ExceptionMessages.ContainsKey.Inject(key));
}
return param;
}
[DebuggerStepThrough]
public static Param<IList<T>> Any<T>(this Param<IList<T>> param, Func<T, bool> predicate)
{
if (!param.Value.Any(predicate))
{
throw CreateForParameterValidation(param, ExceptionMessages.AnyPredicateYieldedNone);
}
return param;
}
[DebuggerStepThrough]
public static Param<List<T>> Any<T>(this Param<List<T>> param, Func<T, bool> predicate)
{
if (!param.Value.Any(predicate))
{
throw CreateForParameterValidation(param, ExceptionMessages.AnyPredicateYieldedNone);
}
return param;
}
[DebuggerStepThrough]
public static Param<ICollection<T>> Any<T>(this Param<ICollection<T>> param, Func<T, bool> predicate)
{
if (!param.Value.Any(predicate))
{
throw CreateForParameterValidation(param, ExceptionMessages.AnyPredicateYieldedNone);
}
return param;
}
[DebuggerStepThrough]
public static Param<Collection<T>> Any<T>(this Param<Collection<T>> param, Func<T, bool> predicate)
{
if (!param.Value.Any(predicate))
{
throw CreateForParameterValidation(param, ExceptionMessages.AnyPredicateYieldedNone);
}
return param;
}
[DebuggerStepThrough]
public static Param<T[]> Any<T>(this Param<T[]> param, Func<T, bool> predicate)
{
if (!param.Value.Any(predicate))
{
throw CreateForParameterValidation(param, ExceptionMessages.AnyPredicateYieldedNone);
}
return param;
}
#endregion
#region Comparable Extensions
public static bool IsLessThan<T>(this IComparable<T> x, T y)
{
return x.CompareTo(y) < 0;
}
public static bool IsGreaterThan<T>(this IComparable<T> x, T y)
{
return x.CompareTo(y) > 0;
}
public static bool IsEqualTo<T>(this IComparable<T> x, T y)
{
return x.CompareTo(y) == 0;
}
[DebuggerStepThrough]
public static Param<T> IsEqualTo<T>(this Param<T> param, T expected) where T : struct, IComparable<T>
{
if (!param.Value.IsEqualTo(expected))
{
throw CreateForParameterValidation(param, ExceptionMessages.IsFailed.Inject(param.Value, expected));
}
return param;
}
[DebuggerStepThrough]
public static Param<T> IsNotEqualTo<T>(this Param<T> param, T expected) where T : struct, IComparable<T>
{
if (param.Value.IsEqualTo(expected))
{
throw CreateForParameterValidation(param, ExceptionMessages.IsNotFailed.Inject(param.Value, expected));
}
return param;
}
[DebuggerStepThrough]
public static Param<T> IsLessThan<T>(this Param<T> param, T limit) where T : struct, IComparable<T>
{
if (!param.Value.IsLessThan(limit))
{
throw CreateForParameterValidation(param, ExceptionMessages.IsNotLt.Inject(param.Value, limit));
}
return param;
}
[DebuggerStepThrough]
public static Param<T> IsLessThanOrEqualTo<T>(this Param<T> param, T limit) where T : struct, IComparable<T>
{
if (param.Value.IsGreaterThan(limit))
{
throw CreateForParameterValidation(param, ExceptionMessages.IsNotLte.Inject(param.Value, limit));
}
return param;
}
[DebuggerStepThrough]
public static Param<T> IsGreaterThan<T>(this Param<T> param, T limit) where T : struct, IComparable<T>
{
if (!param.Value.IsGreaterThan(limit))
{
throw CreateForParameterValidation(param, ExceptionMessages.IsNotGt.Inject(param.Value, limit));
}
return param;
}
[DebuggerStepThrough]
public static Param<T> IsGreaterThanOrEqualTo<T>(this Param<T> param, T limit) where T : struct, IComparable<T>
{
if (param.Value.IsLessThan(limit))
{
throw CreateForParameterValidation(param, ExceptionMessages.IsNotGte.Inject(param.Value, limit));
}
return param;
}
[DebuggerStepThrough]
public static Param<T> IsInRange<T>(this Param<T> param, T min, T max) where T : struct, IComparable<T>
{
if (param.Value.IsLessThan(min))
{
throw CreateForParameterValidation(param, ExceptionMessages.IsNotInRangeTooLow.Inject(param.Value, min));
}
if (param.Value.IsGreaterThan(max))
{
throw CreateForParameterValidation(param, ExceptionMessages.IsNotInRangeTooHigh.Inject(param.Value, max));
}
return param;
}
#endregion
#region Guid Extensions
public static Param<Guid> IsNotEmpty(this Param<Guid> param)
{
if (param.Value.Equals(Guid.Empty))
{
throw CreateForParameterValidation(param, ExceptionMessages.IsNotGuid.Inject(param.Value));
}
return param;
}
#endregion
#region Nullable Value Type Extensions
[DebuggerStepThrough]
public static Param<T?> IsNotNull<T>(this Param<T?> param) where T : struct
{
if (param == null || !param.Value.HasValue)
{
throw CreateForNullParameterValidation(param, ExceptionMessages.IsNotNull);
}
return param;
}
#endregion
#region Object Extensions
[DebuggerStepThrough]
public static Param<T> IsNotNull<T>(this Param<T> param) where T : class
{
if (param.Value == null)
{
throw CreateForNullParameterValidation(param, ExceptionMessages.IsNotNull);
}
return param;
}
#endregion
#region String Extensions
[DebuggerStepThrough]
public static Param<string> IsNotNullOrEmpty(this Param<string> param)
{
if (string.IsNullOrEmpty(param.Value))
{
throw CreateForParameterValidation(param, ExceptionMessages.IsNotNullOrEmpty);
}
return param;
}
[DebuggerStepThrough]
public static Param<string> IsNotNullOrWhiteSpace(this Param<string> param)
{
if (string.IsNullOrWhiteSpace(param.Value))
{
throw CreateForParameterValidation(param, ExceptionMessages.IsNotNullOrEmpty);
}
return param;
}
[DebuggerStepThrough]
public static Param<string> HasLengthBetween(this Param<string> param, int minLength, int maxLength)
{
if (string.IsNullOrEmpty(param.Value))
{
throw CreateForParameterValidation(param, ExceptionMessages.IsNotNullOrEmpty);
}
var length = param.Value.Length;
if (length < minLength)
{
throw CreateForParameterValidation(
param,
ExceptionMessages.IsNotInRangeTooShort.Inject(minLength, maxLength, length));
}
if (length > maxLength)
{
throw CreateForParameterValidation(
param,
ExceptionMessages.IsNotInRangeTooLong.Inject(minLength, maxLength, length));
}
return param;
}
[DebuggerStepThrough]
public static Param<string> Matches(this Param<string> param, string pattern)
{
return Matches(param, new Regex(pattern));
}
[DebuggerStepThrough]
public static Param<string> Matches(this Param<string> param, Regex regex)
{
if (!regex.IsMatch(param.Value))
{
throw CreateForParameterValidation(
param,
ExceptionMessages.NoMatch.Inject(param.Value, regex));
}
return param;
}
[DebuggerStepThrough]
public static Param<string> FileExists(this Param<string> param)
{
if (string.IsNullOrEmpty(param.Value))
{
throw CreateForParameterValidation(param, ExceptionMessages.IsNotNullOrEmpty);
}
if (!File.Exists(param.Value))
{
throw CreateForParameterValidation(
param,
ExceptionMessages.FileDoesNotExist.Inject(param.Value));
}
return param;
}
[DebuggerStepThrough]
public static Param<string> DirectoryExists(this Param<string> param)
{
if (string.IsNullOrEmpty(param.Value))
{
throw CreateForParameterValidation(param, ExceptionMessages.IsNotNullOrEmpty);
}
if (!Directory.Exists(param.Value))
{
throw CreateForParameterValidation(
param,
ExceptionMessages.DirectoryDoesNotExist.Inject(param.Value));
}
return param;
}
[DebuggerStepThrough]
public static Param<string> IsGuid(this Param<string> param)
{
Guid guid;
if (!Guid.TryParse(param.Value, out guid))
{
throw CreateForParameterValidation(param, ExceptionMessages.IsNotGuid.Inject(param.Value));
}
return param;
}
[DebuggerStepThrough]
public static Param<string> IsNumber(this Param<string> param)
{
long number;
if (long.TryParse(param.Value, out number))
{
throw CreateForParameterValidation(param, ExceptionMessages.IsNotNumber.Inject(param.Value));
}
return param;
}
[DebuggerStepThrough]
public static Param<string> IsEqualTo(this Param<string> param, string expected, StringComparison? comparison = null)
{
if (!StringEquals(param.Value, expected, comparison))
{
throw CreateForParameterValidation(
param,
ExceptionMessages.IsFailed.Inject(param.Value, expected));
}
return param;
}
[DebuggerStepThrough]
public static Param<string> IsNotEqualTo(this Param<string> param, string expected, StringComparison? comparison = null)
{
if (StringEquals(param.Value, expected, comparison))
{
throw CreateForParameterValidation(
param,
ExceptionMessages.IsFailed.Inject(param.Value, expected));
}
return param;
}
private static bool StringEquals(string x, string y, StringComparison? comparison = null)
{
return comparison.HasValue
? string.Equals(x, y, comparison.Value)
: string.Equals(x, y);
}
public static string Inject(this string format, params object[] args)
{
return string.Format(format, args);
}
#endregion
#region Type Extensions
private static class PrimitiveTypes
{
internal static readonly Type IntType = typeof(int);
internal static readonly Type LongType = typeof(long);
internal static readonly Type ShortType = typeof(short);
internal static readonly Type DecimalType = typeof(decimal);
internal static readonly Type DoubleType = typeof(double);
internal static readonly Type FloatType = typeof(float);
internal static readonly Type BoolType = typeof(bool);
internal static readonly Type DateTimeType = typeof(DateTime);
internal static readonly Type StringType = typeof(string);
}
[DebuggerStepThrough]
public static TypeParam IsInt(this TypeParam param)
{
return IsOfType(param, PrimitiveTypes.IntType);
}
[DebuggerStepThrough]
public static TypeParam IsLong(this TypeParam param)
{
return IsOfType(param, PrimitiveTypes.LongType);
}
[DebuggerStepThrough]
public static TypeParam IsShort(this TypeParam param)
{
return IsOfType(param, PrimitiveTypes.ShortType);
}
[DebuggerStepThrough]
public static TypeParam IsFloat(this TypeParam param)
{
return IsOfType(param, PrimitiveTypes.FloatType);
}
[DebuggerStepThrough]
public static TypeParam IsDecimal(this TypeParam param)
{
return IsOfType(param, PrimitiveTypes.DecimalType);
}
[DebuggerStepThrough]
public static TypeParam IsDouble(this TypeParam param)
{
return IsOfType(param, PrimitiveTypes.DoubleType);
}
[DebuggerStepThrough]
public static TypeParam IsBool(this TypeParam param)
{
return IsOfType(param, PrimitiveTypes.BoolType);
}
[DebuggerStepThrough]
public static TypeParam IsDateTime(this TypeParam param)
{
return IsOfType(param, PrimitiveTypes.DateTimeType);
}
[DebuggerStepThrough]
public static TypeParam IsString(this TypeParam param)
{
return IsOfType(param, PrimitiveTypes.StringType);
}
[DebuggerStepThrough]
private static TypeParam IsOfType(TypeParam param, Type type)
{
if (param.Type != type)
{
throw CreateForParameterValidation(param, ExceptionMessages.IsNotOfType.Inject(param.Type.FullName));
}
return param;
}
#endregion
#region Fluent Extensions
[DebuggerStepThrough]
public static Param<T> And<T>(this Param<T> param)
{
return param;
}
#endregion
#region Exception Factory
private static ArgumentException CreateForParameterValidation(Param param, string message)
{
return new ArgumentException(
param.Message == null
? message
: string.Concat(message, Environment.NewLine, param.Message()),
param.Name);
}
private static ArgumentNullException CreateForNullParameterValidation(Param param, string message)
{
return new ArgumentNullException(
param.Name,
param.Message == null
? message
: string.Concat(message, Environment.NewLine, param.Message()));
}
private static InvalidOperationException CreateForInvalidOperation(Param param, string message)
{
var exceptionMessage = string.Format(message, param.Name);
return new InvalidOperationException(
param.Message == null
? exceptionMessage
: string.Concat(exceptionMessage, Environment.NewLine, param.Message()));
}
#endregion
#region Exception Messages
private static class ExceptionMessages
{
public static readonly string IsNotTrue = "Expected an expression that evaluates to true.";
public static readonly string IsNotFalse = "Expected an expression that evaluates to false.";
public static readonly string IsEmptyCollection = "Empty collection is not allowed.";
public static readonly string SizeIsWrong = "Expected size '{0}' but found '{1}'.";
public static readonly string IsFailed = "Value '{0}' is not '{1}'.";
public static readonly string IsNotFailed = "Value '{0}' is '{1}', which was not expected.";
public static readonly string IsNotLt = "value '{0}' is not lower than limit '{1}'.";
public static readonly string IsNotLte = "value '{0}' is not lower than or equal to limit '{1}'.";
public static readonly string IsNotGt = "value '{0}' is not greater than limit '{1}'.";
public static readonly string IsNotGte = "value '{0}' is not greater than or equal to limit '{1}'.";
public static readonly string IsNotInRangeTooLow = "value '{0}' is < min '{1}'.";
public static readonly string IsNotInRangeTooHigh = "value '{0}' is > max '{1}'.";
public static readonly string IsNotNull = "Value can not be null.";
public static readonly string IsNotNullOrWhiteSpace = "The string can't be left empty, null or consist of only whitespaces.";
public static readonly string IsNotNullOrEmpty = "The string can't be null or empty.";
public static readonly string IsNotInRangeTooShort = "The string is not long enough. Must be between '{0}' and '{1}' but was '{2}' characters long.";
public static readonly string IsNotInRangeTooLong = "The string is too long. Must be between '{0}' and '{1}'. Must be between '{0}' and '{1}' but was '{2}' characters long.";
public static readonly string NoMatch = "value '{0}' does not match '{1}'";
public static readonly string IsNotOfType = "The param is not of expected type: '{0}'.";
public static readonly string IsNotClassWasNull = "The param was expected to be a class, but was NULL.";
public static readonly string IsNotClass = "The param was expected to be a class, but was type of: '{0}'.";
public static readonly string InvalidOperationException = "Could not perform operation due to invalid state of '{0}'.";
public static readonly string IsEmptyGuid = "Empty Guid is not allowed.";
public static readonly string ContainsKey = "Key '{0}' does not exist.";
public static readonly string AnyPredicateYieldedNone = "The predicate did not match any elements.";
public static readonly string IsNotGuid = "Value '{0}' is not a valid GUID.";
public static readonly string IsNotNumber = "Value '{0}' is not a valid number.";
public static readonly string FileDoesNotExist = "The specified file '{0}' does not exist.";
public static readonly string DirectoryDoesNotExist = "The specified directory '{0}' does not exist.";
}
#endregion
}
#region Param class
public abstract class Param
{
public const string DefaultName = "";
public Func<string> Message { get; protected set; }
public string Name { get; protected set; }
protected Param(string name, Func<string> message = null)
{
Name = name;
Message = message;
}
}
public class Param<T> : Param
{
public T Value { get; protected set; }
public Param(T value, string name = "", Func<string> message = null)
: base(name, message)
{
Value = value;
Name = name;
}
public Param<T> WithCustomMessage(Func<string> message)
{
Message = message;
return this;
}
}
#endregion
#region TypeParam class
public class TypeParam : Param
{
public TypeParam(string name, Type type)
: base(name)
{
Type = type;
}
public Type Type { get; private set; }
}
#endregion
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment