Argument validation class looks tons better using generics in CLR 2.0
I've had this class around for a long time, finally decided to update it to use generic types instead of tons of overloads. It's tons nicer this way. Contact me if you want a version with XML documentation (which just looks ugly in the blog).
using System; using System.ComponentModel; using System.Diagnostics; namespace IDisposable.Utilities { public static class ArgumentValidation { #region Helper private static string PadWord(string text) { if (String.IsNullOrEmpty(text)) return string.Empty; else return text + " "; } #endregion public static void ArgumentDifferentTypeCheck(object value, string name, Type type) { ArgumentValidation.ArgumentNullCheck(value, "value"); ArgumentValidation.ArgumentNullCheck(type, "type"); if (value.GetType() != type) { throw new ArgumentException( string.Format("Argument {0}must be of type {1}.", ArgumentValidation.PadWord(name), type.Name), name); } } public static void ArgumentIncompatibleTypeCheck(object value, string name, Type type) { ArgumentValidation.ArgumentNullCheck(value, "value"); ArgumentValidation.ArgumentNullCheck(type, "type"); if (!type.IsAssignableFrom(value.GetType())) { throw new ArgumentException( string.Format("Argument {0}must be compatible with type {1}.", ArgumentValidation.PadWord(name), type.Name), name); } } public static void ArgumentNullCheck(object value, string name) { if (null == value) { throw new ArgumentNullException(name, string.Format("Argument {0}cannot be null.", ArgumentValidation.PadWord(name))); } } public static void ArrayArgumentDifferentRank(Array value, string name, int rank) { ArgumentValidation.ArgumentNullCheck(value, "value"); if (value.Rank != rank) { throw new RankException(string.Format("Argument {0}must be " + "an array with {1} dimension.", ArgumentValidation.PadWord(name), rank)); } } public static void ArgumentInvalidEnumValueCheck(object value, string name, Type enumType) { Debug.Assert(value.GetType().IsPrimitive || (value.GetType() == typeof(string)) , "Expected a primitive type or a String!"); ArgumentValidation.ArgumentNullCheck(value, "value"); ArgumentValidation.ArgumentNullCheck(enumType, "enumType"); if (enumType.GetCustomAttributes(typeof(FlagsAttribute), true).Length > 0) { throw new ArgumentException(string.Format( "Cannot validate against the type {0} because it has the custom attribute FlagsAttribute." , enumType), "enumType"); } if (!Enum.IsDefined(enumType, value)) { if (value.GetType() == typeof(string)) { // Let the value argument be int.MaxValue if a string was passed in. throw new InvalidEnumArgumentException(name, int.MaxValue, enumType); } else { int valueInt32 = 0; TypeConverter typeConverter = TypeDescriptor.GetConverter( Enum.GetUnderlyingType(enumType)); try { valueInt32 = (int)typeConverter.ConvertTo(value, typeof(int)); } catch (OverflowException) { // Let the value argument be 0 if it overflows Int32. } throw new InvalidEnumArgumentException(name, valueInt32, enumType); } } } public static void ArgumentOutOfRangeCheck(T value, string name, T minValue, T maxValue) where T : IComparable { ArgumentValidation.ArgumentNullCheck(value, "value"); ArgumentValidation.ArgumentIncompatibleTypeCheck(minValue, "minValue", typeof(T)); ArgumentValidation.ArgumentIncompatibleTypeCheck(maxValue, "maxValue", typeof(T)); if (value.CompareTo(minValue) < 0 || 0 < value.CompareTo(maxValue)) { throw new ArgumentOutOfRangeException(name, value , string.Format("Argument {0}must be greater than or equal to {1} and less than or equal to {2}." , ArgumentValidation.PadWord(name), minValue, maxValue)); } } public static void ArgumentOutOfRangeExclusiveCheck (T value, string name, T lowerBound, T upperBound) where T : IComparable { ArgumentValidation.ArgumentNullCheck(value, "value"); ArgumentValidation.ArgumentDifferentTypeCheck(lowerBound, "lowerBound", typeof(T)); ArgumentValidation.ArgumentDifferentTypeCheck(upperBound, "upperBound", typeof(T)); if (lowerBound.CompareTo(upperBound) == 0) { throw new ArgumentException("Arguments lowerBound and upperBound cannot be equal."); } if (value.CompareTo(lowerBound) <= 0 || 0 <= value.CompareTo(upperBound)) { throw new ArgumentOutOfRangeException(name, value, string.Format("Argument {0}must be greater than {1} and less than {2}." , ArgumentValidation.PadWord(name), lowerBound, upperBound)); } } public static void ArgumentOutOfRangeIncludeMaxCheck (T value, string name, T lowerBound, T maxValue) where T : IComparable { ArgumentValidation.ArgumentNullCheck(value, "value"); ArgumentValidation.ArgumentIncompatibleTypeCheck(lowerBound, "lowerBound", typeof(T)); ArgumentValidation.ArgumentIncompatibleTypeCheck(maxValue, "maxValue", typeof(T)); if (value.CompareTo(lowerBound) <= 0 || 0 < value.CompareTo(maxValue)) { throw new ArgumentOutOfRangeException(name, value, string.Format("Argument {0}must be greater than {1} and less than or equal to {2}." , ArgumentValidation.PadWord(name), lowerBound, maxValue)); } } public static void ArgumentOutOfRangeIncludeMinCheck (T value, string name, T minValue, T upperBound) where T : IComparable { ArgumentValidation.ArgumentNullCheck(value, "value"); ArgumentValidation.ArgumentIncompatibleTypeCheck(minValue, "minValue", typeof(T)); ArgumentValidation.ArgumentIncompatibleTypeCheck(upperBound, "upperBound", typeof(T)); if (value.CompareTo(minValue) < 0 || 0 <= value.CompareTo(upperBound)) { throw new ArgumentOutOfRangeException(name, value, string.Format("Argument {0}must be greater than or equal to {1} and less than {2}." , ArgumentValidation.PadWord(name), minValue, upperBound)); } } } }
3 comments:
Can you throw out a .zip link with the .cs and .xml doc? This thing is a goldmine!
Done, see here.
Updated to fix Enum bug
Post a Comment