MVC验证(自动在基类中验证实体的数据有效性),本人最满意的作品之一

说起数据验证,在我的博客中文章不少,有MVC标准验证,有自己架构中用到的验证,但一个共同的问题就是重复的代码量太大,而且破坏了数据库实体本身的层次感!即数据(实体)有效性验证就应该在实体层去实现,不应该推迟到WEB层去做这事,在之前的文章中我介绍了使用统一实体基类来做这事,但需要每个实体都去干预自己的部分(可能大部分情况下,每个实体的某些验证都是相同的,如非空验证),这样,对于懒惰的程序员来说,是件很不爽的事,于是乎,开始想去解决这个问题了。

原来的代码:  

public virtual bool IsValid { get { return (this.GetRuleViolations().Count() == 0); } }
public abstract IEnumerable<RuleViolation> GetRuleViolations();

在派生类中去实现这个GetRuleViolations()方法:

public override IEnumerable<RuleViolation> GetRuleViolations()
     {

           if (this.ConfirmPassword != this.Password && this.ConfirmPassword != this.NewPassword)
             yield return new RuleViolation("两?次?密ü码?必?须?相à同?", "ConfirmPassword");
     }

像上面的代码其实只是作了非空性验证,正常情况下,我们需要为每个非空的字段(属性)去做这样的验证,太悲哀了,于是,想到了下面的解决方法,将非空验证提取到基类中去做这事。

复制代码
  #region 实体验证

    public virtual bool IsValid { get { return (this.GetRuleViolations().Count() == 0); } }
       public virtual IEnumerable<RuleViolation> GetRuleViolations()
        {

           PropertyInfo[] propertyInfo = this.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance);
            foreach (var i in propertyInfo)
            {
                if (i.GetCustomAttributes(typeof(System.Data.Linq.Mapping.ColumnAttribute), false) != null
                    && i.GetCustomAttributes(typeof(System.Data.Linq.Mapping.ColumnAttribute), false).Count() > 0
                    && !((System.Data.Linq.Mapping.ColumnAttribute)i.GetCustomAttributes(typeof(System.Data.Linq.Mapping.ColumnAttribute), false)[0]).CanBeNull
                    && !((System.Data.Linq.Mapping.ColumnAttribute)i.GetCustomAttributes(typeof(System.Data.Linq.Mapping.ColumnAttribute), false)[0]).IsPrimaryKey)
                    if (i.GetValue(this, null) == null || string.IsNullOrEmpty(i.GetValue(this, null).ToString()))
                        yield return new RuleViolation("*", i.Name);
            }
        }
         #endregion
复制代码

我们可以看到,基类中的GetRuleViolations() 已经被改造成了虚方法,即它要去做一些派生类共用的工作,本例是“非空验证”,而如果有个性化的验证,还是需要在指定的实体中去实现,代码可能是这样:

复制代码
public override IEnumerable<RuleViolation> GetRuleViolations()
       {
           #region 得到基类的非空验证迭代结果

          foreach (var violation in base.GetRuleViolations())
               yield return violation;
           #endregion
           if (this.ConfirmPassword != this.Password && this.ConfirmPassword != this.NewPassword)
               yield return new RuleViolation("两?次?密ü码?必?须?相à同?", "ConfirmPassword");
       }
复制代码

恩,这样的设计我才算是满意,一句话,共用的放在基类的虚方法,个性化的需要在实体类中复写基类方法,通过override关键字可以复写基类的抽象或方法,而不会覆盖掉它们,再配合base关键字,就可以调用基类的方法了,呵呵。

posted @   张占岭  阅读(1961)  评论(2编辑  收藏  举报
编辑推荐:
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 一文读懂知识蒸馏
· 终于写完轮子一部分:tcp代理 了,记录一下
点击右上角即可分享
微信分享提示