程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> 關於.NET >> Castle ActiveRecord學習實踐(8) 數據有效性的驗證

Castle ActiveRecord學習實踐(8) 數據有效性的驗證

編輯:關於.NET

主要內容

1.概述

2.使用Validation

3.如何擴展

4.深入分析驗證

一.概述

在錄入數據時,對數據有效性的驗證是必不可少的,很多時候我們在UI層上就會做一層驗證,但有時也需要在底層做一些必要的處理,這就要用到ActiveRecord中的數據有效性的驗證。ActiveRecord為我們提供了如下幾個驗證:

n  ValidateEmail

n  ValidateIsUnique

n  ValidateRegExp

n  ValidateNotEmpty

n  ValidateConfirmation

二.如何使用

為了使用上面這些驗證,我們必須用ActiveRecordValidationBase來代替ActiveRecordBase,即實體類必須繼承於ActiveRecordValidationBase。

[ActiveRecord("Customs")]
public class Custom : ActiveRecordValidationBase
{
  //
}

ActiveRecordValidationBase類為我們提供了如下一個方法和屬性:

方法|屬性 說明

IsValid() 返回驗證是否通過

ValidationErrorMessages 獲取驗證錯誤信息數組

下面看一個完整的例子代碼,在這個程序中我們需要驗證用戶名不能為空,Email地址、郵政編碼、電話號碼的格式是否正確

[ActiveRecord("Customs")]
public class Custom : ActiveRecordValidationBase
{
    private int _id;
    private string _name;
    private string _email;
    private string _address;
    private string _post;
    private string _phone;
    [PrimaryKey(PrimaryKeyType.Native)]
    public int ID
    {
        get { return this._id; }
        set { this._id = value; }
    }
    [Property,ValidateNotEmpty]
    public string Name
    {
        get { return this._name; }
        set { this._name = value; }
    }
    [Property,ValidateEmail]
    public string Email
    {
        get { return this._email; }
        set { this._email = value; }
    }
    [Property]
    public string Address
    {
        get { return this._address; }
        set { this._address = value; }
    }
    [Property,ValidateRegExp(@"\d{6}")]
    public string Post
    {
        get { return this._post; }
        set { this._post = value; }
    }
    [Property,ValidateRegExp(@"(\(\d{3,4}\)|\d{3,4}-)?\d{8}")]
    public string Phone
    {
        get { return this._phone; }
        set { this._phone = value; }
    }
    public static void DeleteAll()
    {
        ActiveRecordBase.DeleteAll(typeof(Custom));
    }
    public static Custom[] FindAll()
    {
        return ((Custom[])(ActiveRecordBase.FindAll(typeof(Custom))));
    }
}

編寫一些簡單的測試代碼,大家有興趣可以看一下:

[Test]
public void TestNameValidation()
{
  //姓名為空
  Custom custom = new Custom();
  custom.Address = "TianJin";
  custom.Email = "[email protected]";
   custom.Phone = "022-24096356";
  custom.Post = "300192";
  //錯誤消息數
  int expectedError = 1;

  Assert.IsFalse(custom.IsValid());
  Assert.AreEqual(expectedError,custom.ValidationErrorMessages.Length);
}

[Test]
public void TestPostValidation()
{
  //郵政編碼錯誤、Email錯誤
  Custom custom = new Custom();
  custom.Name = "Terry Lee";
  custom.Email = "lhj_cauc#hotmail.com";
  custom.Phone = "022-24096356";
  custom.Post = "222t";
  custom.Address = "Tianjin";

  //錯誤消息數
  int expectedError = 2;
  Assert.IsFalse(custom.IsValid());
  Assert.AreEqual(expectedError,custom.ValidationErrorMessages.Length);
}

[Test]
public void TestAllValidation()
{
  //全部正確
  Custom custom = new Custom();
  custom.Name = "Terry Lee";
  custom.Email = "[email protected]";
   custom.Phone = "022-24096335";
  custom.Address = "TianJin";
  custom.Post = "300192";

  //錯誤消息數
  int expectedError = 0;
  Assert.IsTrue(custom.IsValid());
  Assert.AreEqual(expectedError,custom.ValidationErrorMessages.Length);
}

三.如何擴展

上面這些驗證已經能夠滿足我們絕大多數的需求,但是我們也可以去添加自己的驗證。來看看ActiveRecord中的Validation的類結構圖(只畫出了部分)

通過上圖可以看到,如果想添加自己的驗證,需要有一個繼承AbstractValidator和繼承於AbstractValidationAttribute的類就可以了,具體可以參考ActiveRecord的代碼。

四.深入分析驗證

通過上面的分析我們都知道所有的實體類都繼承於ActiveRecordValidationBase基類,那麼ActiveRecord是如何通過特性來進行驗證的呢?下面我們結合源碼進一步分析一下。

我們在屬性上加上了驗證, Attribute並不做任何實質性的工作,它只是調用驗證器進行驗證,先來看一下ValidateNotEmptyAttribute的代碼:

[Serializable]
public class ValidateNotEmptyAttribute : AbstractValidationAttribute
{
  public ValidateNotEmptyAttribute() : base(new NullCheckValidator())
  {
  }

  public ValidateNotEmptyAttribute(String errorMessage) : base(new NullCheckValidator(), errorMessage)
  {

  }
}

所有驗證工作都是在Validator中進行的,以NullCheckValidator為例來看它做了什麼操作:

[Serializable]
public class NullCheckValidator : AbstractValidator
{
  public NullCheckValidator()
  {

  }

  public override bool Perform(object instance, object fieldValue)
  {
    return fieldValue != null && fieldValue.ToString().Length != 0;
  }

  protected override string BuildErrorMessage()
  {
    return String.Format("{0} is not optional.", Property.Name);
  }
}

這個類其實很簡單,但我們注意到有一個Perform的方法,正是這個方法完成了驗證工作,拿這個例子來說,如果字段的值為空或長度等於零就返回false,否則為true。對於正則驗證等其他的也都是在這個方法中完成。回到ActiveRecordValidationBase中去,看這個類初始化的時候做了什麼操作?

/**//// <summary>
/// Constructs an ActiveRecordValidationBase
/// </summary>
public ActiveRecordValidationBase()
{
  CollectValidators( this.GetType() );
}

/**//// <summary>
/// Collect the validations applied to this class properties.
/// </summary>
/// <param name="targetType"></param>
private void CollectValidators( Type targetType )
{
  ActiveRecordModel model = GetModel( targetType );

  if (model == null)
  {
    throw new ActiveRecordException("Seems that the framework wasn't initialized properly. (ActiveRecordModel could not obtained)");
  }

  __validators.AddRange( model.Validators );

  while( model.Parent != null )
  {
    __validators.AddRange( model.Parent.Validators );

    model = model.Parent;
  }
}

在初始化的時候,通過ActiveRecordModel獲取到當前實體所有屬性對應的Validator,並放在了一個ArrayList中去,然後在IsValid()方法中再逐一調用Validator的Perform()方法來判斷驗證是否通過,因為所有的驗證器都實現了Ivalidator。如果有驗證發生錯誤,則把錯誤信息保存再一個字符數組中,可以通過屬性ValidationErrorMessages來獲取錯誤信息。

public bool IsValid()
{
  ArrayList errorlist = new ArrayList();
  __failedProperties = new Hashtable();

  foreach(IValidator validator in __validators)
  {
    if (!validator.Perform(this))
    {
      String errorMessage = validator.ErrorMessage;
      errorlist.Add( errorMessage );

      ArrayList items = null;

      if (__failedProperties.Contains(validator.Property))
      {
        items = (ArrayList) __failedProperties[validator.Property];
      }
      else
      {
        items = new ArrayList();

        __failedProperties[validator.Property] = items;
      }

      items.Add(errorMessage);
    }
  }

  _errorMessages = (String[]) errorlist.ToArray( typeof(String) );

  return errorlist.Count == 0;
}

在ActiveRecord中的數據有效性驗證就介紹到這兒了,下篇我會介紹ActiveRecord常用的一些技巧。[非常感謝idior大哥提出的意見]

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved