LLBL Gen 3.x 原始碼追蹤與解析 驗證Validation的原理和流程

來源:互聯網
上載者:User

先看應用程式如何應用驗證。以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

這就是驗證的完整堆棧流程。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.