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

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

posted @ 2011-08-29 09:38  信息化建设  阅读(1507)  评论(0编辑  收藏  举报