// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。 // // 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。 // // 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任! namespace Admin.NET.Core; /// /// 条件必填参数验证特性(支持多条件判断) /// 当另一个属性的值满足指定条件时,验证当前属性是否非空。 /// /// /// // 实例1 /// [RequiredIF(nameof(TarProperty), 1, ErrorMessage = "TarProperty为1时,SomeProperty不能为空")]
/// public string SomeProperty { get; set; }
///
/// /// // 实例2 /// [RequiredIF(nameof(TarProperty), 1, Operator.NotEqual, ErrorMessage = "TarProperty不为1时,SomeProperty不能为空")]
/// public string SomeProperty { get; set; }
///
/// /// // 实例3 /// [RequiredIF(nameof(TarProperty), new[]{ 1, 2 }, Operator.Contains, ErrorMessage = "TarProperty包含为1或2时,SomeProperty不能为空")]
/// public string SomeProperty { get; set; }
///
/// /// // 实例4 /// [RequiredIF(nameof(TarProperty), new[]{ 1, 2 }, Operator.NotContains, ErrorMessage = "TarProperty不包含1和2时,SomeProperty不能为空")]
/// public string SomeProperty { get; set; }
///
[AttributeUsage(AttributeTargets.Property)] public sealed class RequiredIFAttribute : ValidationAttribute { /// /// 依赖的属性名称 /// private string PropertyName { get; set; } /// /// 目标比较值 /// private object TargetValue { get; set; } /// /// 比较运算符 /// private Operator Comparison { get; set; } public RequiredIFAttribute(string propertyName, object targetValue = null, Operator comparison = Operator.Equal) { PropertyName = propertyName; TargetValue = targetValue; Comparison = comparison; } /// /// 验证属性值是否符合要求 /// /// 当前属性的值 /// 验证上下文 /// 验证结果 protected override ValidationResult IsValid(object value, ValidationContext validationContext) { ArgumentNullException.ThrowIfNull(validationContext); var instance = validationContext.ObjectInstance; var targetProperty = instance.GetType().GetProperty(PropertyName); if (targetProperty == null) return new ValidationResult($"找不到属性: {PropertyName}"); var targetValue = targetProperty.GetValue(instance); if (!ShouldValidate(targetValue)) { return ValidationResult.Success; } return IsValueEmpty(value) ? new ValidationResult(ErrorMessage ?? $"{validationContext.MemberName}不能为空") : ValidationResult.Success; } /// /// 判断是否需要进行验证 /// /// 依赖属性的值 /// 是否需要验证 private bool ShouldValidate(object targetValue) { if (TargetValue == null) return targetValue == null || (targetValue is string str && string.IsNullOrWhiteSpace(str)) || targetValue is long and 0; return TargetValue is IEnumerable enumerable and not string ? enumerable.Cast().Any(item => CompareValues(targetValue, item, Operator.Equal)) : CompareValues(targetValue, TargetValue, Comparison); } /// /// 检查值是否为空 /// /// 要检查的值 /// 值是否为空 private static bool IsValueEmpty(object value) { return value == null || (value is string str && string.IsNullOrWhiteSpace(str)) || value is long and 0; } /// /// 比较两个值 /// /// 源值 /// 目标值 /// 比较运算符 /// 比较结果 private static bool CompareValues(object sourceValue, object targetValue, Operator comparison) { // 处理null值比较 if (sourceValue == null || targetValue == null) { return comparison switch { Operator.Equal => sourceValue == targetValue, Operator.NotEqual => sourceValue != targetValue, _ => false }; } // 处理集合包含操作 if (comparison is Operator.Contains or Operator.NotContains) { if (targetValue is not IEnumerable enumerable) { return false; } bool contains = enumerable.Cast().Any(item => item != null && item.Equals(sourceValue)); return comparison == Operator.Contains ? contains : !contains; } // 处理可比较类型 if (sourceValue is IComparable sourceComparable && targetValue is IComparable targetComparable) { int result = sourceComparable.CompareTo(targetComparable); return comparison switch { Operator.Equal => result == 0, Operator.NotEqual => result != 0, Operator.GreaterThan => result > 0, Operator.LessThan => result < 0, Operator.GreaterThanOrEqual => result >= 0, Operator.LessThanOrEqual => result <= 0, _ => false }; } // 默认比较 bool equals = sourceValue.Equals(targetValue); return comparison == Operator.Equal ? equals : !equals; } } /// /// 比较运算符枚举 /// [SuppressSniffer] [Description("比较运算符枚举")] public enum Operator { /// /// 等于 (==) /// [Description("等于")] Equal, /// /// 不等于 (!=) /// [Description("不等于")] NotEqual, /// /// 大于 (>) /// [Description("大于")] GreaterThan, /// /// 小于 (<) /// [Description("小于")] LessThan, /// /// 大于等于 (>=) /// [Description("大于等于")] GreaterThanOrEqual, /// /// 小于等于 (<=) /// [Description("小于等于")] LessThanOrEqual, /// /// 包含 (包含于集合) /// [Description("包含")] Contains, /// /// 不包含 (不包含于集合) /// [Description("不包含")] NotContains }