using System; using System.Collections.Generic; using System.Text; using iORM.Utility; namespace iORM.Common { #region RangeInterval /// <summary> /// 范围区间类型 /// </summary> public enum RangeIntervalType { /// <summary> /// 闭区间 [Minimum, Maximum] /// </summary> ClosedInterval = 0x00, /// <summary> /// 左闭右开区间 [Minimum, Maximum) /// </summary> LeftCloseedRightOpenedInterval = 0x01, /// <summary> /// 左开右闭区间 (Minimum, Maximum] /// </summary> LeftOpenedRightClosedInterval = 0x10, /// <summary> /// 开区间 (Minimum, Maximum) /// </summary> OpenedInterval = 0x11, } #endregion #region IRange /// <summary> /// 可比较范围接口 /// </summary> /// <typeparam name="T">对象类型</typeparam> public interface IRange<T> where T : IComparable { #region 属性 #region Minimum /// <summary> /// 获得最小值 /// </summary> T Minimum { get;} #endregion #region Maximum /// <summary> /// 获得最大值 /// </summary> T Maximum { get;} #endregion #region IntervalType /// <summary> /// 获得范围区间类型 /// </summary> RangeIntervalType IntervalType { get;} #endregion #endregion #region 方法 #region Contains /// <summary> /// 是否包含 /// </summary> /// <param name="dataValue">值</param> /// <returns>true:包含 false:不包含</returns> bool Contains(T dataValue); #endregion #endregion } #endregion #region Range /// <summary> /// 可比较范围类 /// </summary> /// <typeparam name="T">对象类型</typeparam> [Serializable] public class Range<T> : IRange<T> where T : IComparable { #region 定义 /// <summary> /// 分割符 /// </summary> private const string cstrSplit = "|"; /// <summary> /// 缺省范围区间类型 /// </summary> private const RangeIntervalType DefultIntervalType = RangeIntervalType.ClosedInterval; /// <summary> /// 最小值 /// </summary> private readonly T pMinimum; /// <summary> /// 最大值 /// </summary> private readonly T pMaximum; /// <summary> /// 范围区间类型 /// </summary> private readonly RangeIntervalType pIntervalType; #endregion #region 属性 #region IRange<T> 成员 #region Minimum /// <summary> /// 获得最小值 /// </summary> public T Minimum { get { return this.pMinimum; } } #endregion #region Maximum /// <summary> /// 获得最大值 /// </summary> public T Maximum { get { return this.pMaximum; } } #endregion #region IntervalType /// <summary> /// 获得范围区间类型 /// </summary> public RangeIntervalType IntervalType { get { return pIntervalType; } } #endregion #endregion #region IsNullOrEmpty /// <summary> /// 获得是否为空 /// </summary> /// <returns>如果为 <c>null 或/c> <c>Empty</c> 返回 <c>true</c>, 否则返回 <c>false</c></returns> public bool IsNullOrEmpty { get { return string.IsNullOrEmpty(this.pMinimum.ToString()) && string.IsNullOrEmpty(this.pMaximum.ToString()); } } #endregion #endregion #region 构造函数 /// <summary> /// 构造函数 /// </summary> /// <param name="minimum">最小值</param> /// <param name="maximum">最大值</param> public Range(T minimum, T maximum) : this(minimum, maximum, DefultIntervalType, false) { } /// <summary> /// 构造函数 /// </summary> /// <param name="minimum">最小值</param> /// <param name="maximum">最大值</param> /// <param name="interval">范围区间类型</param> public Range(T minimum, T maximum, RangeIntervalType interval) : this(minimum, maximum, interval, false) { } /// <summary> /// 构造函数 /// </summary> /// <param name="minimum">最小值</param> /// <param name="maximum">最大值</param> /// <param name="autoAdjust">自动调整(根据开始值和结束值的大小自动调整最小值和最大值)</param> public Range(T minimum, T maximum, bool autoAdjust) : this(minimum, maximum, DefultIntervalType, autoAdjust) { } /// <summary> /// 构造函数 /// </summary> /// <param name="minimum">最小值</param> /// <param name="maximum">最大值</param> /// <param name="interval">范围区间类型</param> /// <param name="autoAdjust">自动调整(根据开始值和结束值的大小自动调整最小值和最大值)</param> public Range(T minimum, T maximum, RangeIntervalType interval, bool autoAdjust) { if (autoAdjust) { if (minimum.CompareTo(maximum) <= 0) { this.pMinimum = minimum; this.pMaximum = maximum; } else { this.pMinimum = maximum; this.pMaximum = minimum; } } else { this.pMinimum = minimum; this.pMaximum = maximum; } this.pIntervalType = interval; } #endregion #region 方法 #region IRange<T> 成员 #region Contains /// <summary> /// 是否包含 /// </summary> /// <param name="dataValue">要查找的值</param> /// <returns>如果包含返回 <c>true</c>, 否则返回 <c>false</c></returns> public bool Contains(T dataValue) { return Contains(dataValue, this.pIntervalType); } /// <summary> /// 是否包含 /// </summary> /// <param name="dataValue">要查找的值</param> /// <param name="type">范围区间类型</param> /// <returns>如果包含返回 <c>true</c>, 否则返回 <c>false</c></returns> public bool Contains(T dataValue, RangeIntervalType type) { return IsInRange(dataValue, this.pMinimum, this.pMinimum, type); } #endregion #endregion #region ToString /// <summary> /// 转化成字符串 /// </summary> /// <returns>字符串</returns> public override string ToString() { return this.ToString(cstrSplit); } /// <summary> /// 转化成字符串 /// </summary> /// <param name="split">分割符</param> /// <returns>字符串</returns> public string ToString(string split) { return this.pMinimum.ToString() + split + this.pMaximum.ToString(); } #endregion #region IsInRange /// <summary> /// 值是否在指定的范围内 /// </summary> /// <param name="dataValue">值</param> /// <param name="minimum">最小值</param> /// <param name="maximum">最大值</param> /// <returns>如果值在指定的范围内返回 <c>true</c>, 否则返回 <c>false</c></returns> public static bool IsInRange(T dataValue, T minimum, T maximum) { return IsInRange(dataValue, minimum, maximum, DefultIntervalType); } /// <summary> /// 值是否在指定的范围内 /// </summary> /// <param name="dataValue">值</param> /// <param name="minimum">最小值</param> /// <param name="maximum">最大值</param> /// <param name="type">范围区间类型</param> /// <returns>如果值在指定的范围内返回 <c>true</c>, 否则返回 <c>false</c></returns> public static bool IsInRange(T dataValue, T minimum, T maximum, RangeIntervalType type) { return type == RangeIntervalType.ClosedInterval || type == RangeIntervalType.LeftCloseedRightOpenedInterval ? dataValue.CompareTo(minimum) >= 0 : dataValue.CompareTo(minimum) > 0 && type == RangeIntervalType.ClosedInterval || type == RangeIntervalType.LeftOpenedRightClosedInterval ? dataValue.CompareTo(maximum) <= 0 : dataValue.CompareTo(maximum) < 0; } #endregion #region GetInstance /// <summary> /// 获得实体 /// </summary> /// <param name="minimum">最小值</param> /// <param name="maximum">最大值</param> /// <returns>实体</returns> public static Range<T> GetInstance(T minimum, T maximum) { return Range<T>.GetInstance(minimum, maximum, RangeIntervalType.ClosedInterval, false); } /// <summary> /// 获得实体 /// </summary> /// <param name="minimum">最小值</param> /// <param name="maximum">最大值</param> /// <param name="type">范围区间类型</param> /// <returns>实体</returns> public static Range<T> GetInstance(T minimum, T maximum, RangeIntervalType type) { return Range<T>.GetInstance(minimum, maximum, type, false); } /// <summary> /// 获得实体 /// </summary> /// <param name="minimum">最小值</param> /// <param name="maximum">最大值</param> /// <param name="autoAdjust">自动调整(根据开始值和结束值的大小自动调整开始值和结束值)</param> /// <returns>实体</returns> public static Range<T> GetInstance(T minimum, T maximum, bool autoAdjust) { return Range<T>.GetInstance(minimum, maximum, RangeIntervalType.ClosedInterval, autoAdjust); } /// <summary> /// 获得实体 /// </summary> /// <param name="minimum">最小值</param> /// <param name="maximum">最大值</param> /// <param name="type">范围区间类型</param> /// <param name="autoAdjust">自动调整(根据开始值和结束值的大小自动调整最小值和最大值)</param> /// <returns>实体</returns> public static Range<T> GetInstance(T minimum, T maximum, RangeIntervalType type, bool autoAdjust) { return new Range<T>(minimum, maximum, type, autoAdjust); } /// <summary> /// 获得实体 /// </summary> /// <param name="value">值</param> /// <returns>实体</returns> public static Range<string> GetInstance(string value) { return Range<string>.GetInstance(value, cstrSplit, false); } /// <summary> /// 获得实体 /// </summary> /// <param name="value">值</param> /// <param name="split">分割符</param> /// <returns>实体</returns> public static Range<string> GetInstance(string value, string split) { return Range<string>.GetInstance(value, split, false); } /// <summary> /// 获得实体 /// </summary> /// <param name="value">值</param> /// <param name="split">分割符</param> /// <param name="autoAdjust">自动调整(根据开始值和结束值的大小自动调整开始值和结束值)</param> /// <returns>实体</returns> public static Range<string> GetInstance(string value, string split, bool autoAdjust) { return new Range<string>(StringUtility.LeftOfSplit(value, split), StringUtility.RightOfSplit(value, split), autoAdjust); } #endregion #region Guard /// <summary> /// 确保范围的准确性 /// </summary> /// <param name="dataValue">参数值</param> public void Guard(T dataValue) { Guard(dataValue, "参数值"); } /// <summary> /// 确保范围的准确性 /// </summary> /// <param name="dataValue">参数值</param> /// <param name="name">参数名称</param> public void Guard(T dataValue, string argumentName) { if (!Contains(dataValue)) ThrowArgumentOutOfRangeException(argumentName, pMinimum, pMaximum); } #endregion #region GuardInRange /// <summary> /// 确保值在指定的范围内 /// </summary> /// <param name="dataValue">参数值</param> /// <param name="minimum">最小值</param> /// <param name="maximum">最大值</param> public static void GuardInRange(T dataValue, T minimum, T maximum) { GuardInRange(dataValue, minimum, maximum, DefultIntervalType); } /// <summary> /// 确保值在指定的范围内 /// </summary> /// <param name="dataValue">参数值</param> /// <param name="minimum">最小值</param> /// <param name="maximum">最大值</param> /// <param name="argumentName">参数名称</param> public static void GuardInRange(T dataValue, T minimum, T maximum, string argumentName) { GuardInRange(dataValue, minimum, maximum, argumentName, DefultIntervalType); } /// <summary> /// 确保值在指定的范围内 /// </summary> /// <param name="dataValue">参数值</param> /// <param name="minimum">最小值</param> /// <param name="maximum">最大值</param> /// <param name="type">范围区间类型</param> public static void GuardInRange(T dataValue, T minimum, T maximum, RangeIntervalType type) { GuardInRange(dataValue, minimum, maximum, "参数值", type); } /// <summary> /// 确保值在指定的范围内 /// </summary> /// <param name="dataValue">参数值</param> /// <param name="minimum">最小值</param> /// <param name="maximum">最大值</param> /// <param name="argumentName">参数名称</param> /// <param name="type">范围区间类型</param> public static void GuardInRange(T dataValue, T minimum, T maximum, string argumentName, RangeIntervalType type) { if (!IsInRange(dataValue, minimum, maximum, type)) ThrowArgumentOutOfRangeException(argumentName, minimum, maximum); } #endregion #region ThrowArgumentOutOfRangeException /// <summary> /// 抛出参数值超出允许取值范围时的异常 /// </summary> /// <param name="argumentName">参数名称</param> /// <param name="minimum">最小值</param> /// <param name="maximum">最大值</param> private static void ThrowArgumentOutOfRangeException(string argumentName, T minimum, T maximum) { ThrowArgumentOutOfRangeException(argumentName, minimum, maximum, DefultIntervalType); } /// <summary> /// 抛出参数值超出允许取值范围时的异常 /// </summary> /// <param name="argumentName">参数名称</param> /// <param name="minimum">最小值</param> /// <param name="maximum">最大值</param> /// <param name="type">范围区间类型</param> private static void ThrowArgumentOutOfRangeException(string argumentName, T minimum, T maximum, RangeIntervalType type) { if (string.IsNullOrEmpty(argumentName)) throw new ArgumentNullException("参数名称不可为空"); string strFormat = string.Empty; switch (type) { case RangeIntervalType.ClosedInterval: strFormat = "{0}必须在 {1} 和 {2} 之内"; break; case RangeIntervalType.LeftCloseedRightOpenedInterval: strFormat = "{0}必须不小于 {1} 且小于 {2}"; break; case RangeIntervalType.LeftOpenedRightClosedInterval: strFormat = "{0}必须大于 {1} 且不大于 {2}"; break; case RangeIntervalType.OpenedInterval: strFormat = "{0}必须在 {1} 和 {2} 之间"; break; } throw new ArgumentOutOfRangeException(string.Format(strFormat, argumentName, minimum, maximum)); } #endregion #endregion } #endregion }