zoukankan      html  css  js  c++  java
  • LLBL Gen 3.x 源代码追踪与解析 验证Validation的原理和流程

    先看应用程序如何应用验证。以SalesOrderHeaderEntity为例子。
    常见的三种验证:
    1)保存之前的验证,重写ValidateEntityBeforeSave
    2) 删除前的验证,重写ValidateEntityBeforeDelete
    3) 属性获取值之后的验证,重写ValidateFieldValue

    先讲解一个基本的模式,基类中的设计virtual方法,派生中中override,我们在运行时,会调用实际类型的方法
    public class  A

       public virtual Do() {  }
    }
    public class B: A
    {  
       public override Do() { }
    }
    当以这种方法调用时
    A  obj=new B():

    obj.Do();
    它会根据obj的实际类型,调用对应的方法

    验证代码的书写

    [Serializable] 
    public partial class SalesOrderHeaderValidator : ValidatorBase 

       // __LLBLGENPRO_USER_CODE_REGION_START ValidationCode 
       删除采购单前的验证,比如采购单还在被合同contact引用,则不允许删除 
      public override void ValidateEntityBeforeDelete(IEntityCore involvedEntity) 
       { 
             base.ValidateEntityBeforeDelete(involvedEntity); 
             SalesOrderHeaderEntity salesOrder = (SalesOrderHeaderEntity)involvedEntity; 
             if (salesOrder.TotalDue != 0) 
                 throw new Exception("Total due zero not allow for this period");

        } 
       保存采购单前的验证,常常是验证必须输入值的字段

       public override void ValidateEntityBeforeSave(IEntityCore involvedEntity) 
       { 
              base.ValidateEntityBeforeSave(involvedEntity); 
              SalesOrderHeaderEntity salesOrder = (SalesOrderHeaderEntity)involvedEntity; 
              if(salesOrder.TaxAmt>1000)
                    throw new Exception("unable to deal with tax more than 1000"); 
        }  
       采购单的属性值发生改变时,应用此处的验证,比如,当获取截止日期后,要验证它不能小于当前日期

      public override bool ValidateFieldValue(IEntityCore involvedEntity, int fieldIndex, object value) 
         {
                bool result = base.ValidateFieldValue(involvedEntity, fieldIndex, value);
                if (!result)
                    return false;

                SalesOrderHeaderEntity salesOrder = (SalesOrderHeaderEntity)involvedEntity;

                switch ((SalesOrderHeaderFieldIndex)fieldIndex)
                {
                    case SalesOrderHeaderFieldIndex.DueDate:
                           return ValidateDueDate(salesOrder, (DateTime)value);            
                }
                return true;
            }

            private bool ValidateDueDate(SalesOrderHeaderEntity salesOrder, DateTime value)
            {
                if(value.CompareTo(DateTime.Now) < 0)
                    throw new Exception("Due date cannot be less than today");
                return true;
            }   
    }

    挂接到验证代码到实体中

    重写OnInitialized方法,给Validator 属性指定验证器
    protected override void OnInitialized()
    {
           base.OnInitialized(); 
            //Assign validator
           this.Validator =new SalesOrderHeaderValidator();
    }

    追踪删除采购单的堆栈

    先设计一个删除的采购单的测试方法

    [TestMethod]
    public void TestDeleteSalesOrderHeader()
    {
             DataAccessAdapter adapter = new DataAccessAdapter(ConnectionString);
             SalesOrderHeaderEntity salesOrder = new SalesOrderHeaderEntity(43659);
             adapter.DeleteEntity(salesOrder);            
    }

    进入DataAccessAdapterBase的方法
    public bool DeleteEntity(IEntity2 entityToDelete)
    {
             return DeleteEntity(entityToDelete, null);
    }

    调用它的重载overload方法

    public virtual bool DeleteEntity(IEntity2 entityToDelete, IPredicateExpression deleteRestriction)
    {

           EntityBase2 entityToDeleteAsEntityBase2 = (EntityBase2)entityToDelete;
           entityToDeleteAsEntityBase2.CallValidateEntityBeforeDelete();
    }

    进入EntityBase2的CallValidateEntityBeforeDelete
    internal void CallValidateEntityBeforeDelete()
    {
           OnValidateEntityBeforeDelete();
    }
    继续进入OnValidateEntityBeforeDelete方法
    protected virtual void OnValidateEntityBeforeDelete()
            {
                if( _validator != null )
                {
                    _validator.ValidateEntityBeforeDelete( this );
                }
            }

    至此就进入到了我在文章开头写的SalesOrderHeaderValidator的ValidateEntityBeforeDelete方法
    再来看一下ValidatorBase 中的虚拟方法ValidateEntityBeforeDelete

    [Serializable]
    public abstract class ValidatorBase : IValidator
    {

            public virtual void ValidateEntityBeforeDelete( IEntityCore involvedEntity )
            {
                // nop
            }


    验证属性值

    再来看属性设置时的验证,这种验证方法可以验证程序对采购单的任何属性的复制行为。比如,业务规则是,任何时间,采购单的截止日期都不能小于输入采购单的当天,代码如下,
    SalesOrderHeaderEntity salesOrder = new SalesOrderHeaderEntity(2068);
    salesOrder.DueDate = DateTime.Now.AddDays(-1); //这里设置DueDate 的值为昨天,违反了业务规则
    来追踪它的堆栈,进入DueDate属性的set方法

    public virtual System.DateTime DueDate
            {
                  set    { SetValue((int)SalesOrderHeaderFieldIndex.DueDate, value); }
            }

    进入EntityBase2的SetValue方法
    protected bool SetValue(int fieldIndex, object value)
            {
                return SetValue(fieldIndex, value, true);
            }

    同名的重载方法

    protected bool SetValue(int fieldIndex, object value, bool performDesyncForFKFields)
            {

                // set value is not the same as the value to set, proceed
                if(ValidateValue(fieldToSet, ref valueToSet, fieldIndex))
    进入ValidateValue方法

    private bool ValidateValue(IFieldInfo fieldToValidate, ref object value, int fieldIndex)
            {
                   // perform custom validation.
                    validationResult = (OnValidateFieldValue(fieldIndex, value));

              }
    流程进入OnValidateFieldValue方法

    protected virtual bool OnValidateFieldValue( int fieldIndex, object value )
            {
                bool returnValue = true;
                if( _validator != null )
                {
                    returnValue = _validator.ValidateFieldValue(this, fieldIndex, value );
                }
                return returnValue;
            }

    请注意看这一句returnValue = _validator.ValidateFieldValue(this, fieldIndex, value ),它会进入我在开头重写的ValidateFieldValue的方法里面,最后就是进入自定义的方法ValidateDueDate

    image

    这就是验证的完整堆栈流程。

  • 相关阅读:
    优化不易,且写且珍惜
    作为过来人的感悟:进了小公司的程序员如何翻身进入大公司
    腾讯/阿里/百度 BAT人才体系的职位层级、薪酬、晋升标准
    校招生向京东发起的“攻势”,做到他这样,你,也可以
    通过Java 线程堆栈进行性能瓶颈分析
    基于Spring Cloud的微服务落地
    多线程技术使用指南
    Android 处理含有EditText的Activity虚拟键盘
    Android ListView的监听事件
    Android 开源框架Universal-Image-Loader完全解析(一)--- 基本介绍及使用
  • 原文地址:https://www.cnblogs.com/JamesLi2015/p/2157344.html
Copyright © 2011-2022 走看看