2012-09-07 38 views
0

我有一個實現INotifyPropertyChanged的父類,父類有多個孩子。孩子們有不同的屬性,都稱爲PropertyChanged。我想添加驗證,但我真的不想爲每個子類都寫驗證。驗證規則是從數據庫提供的,所以我最終必須爲每個孩子抽取驗證規則,然後根據規則檢查值。如果我這樣做了,我認爲它會有太多冗餘代碼,並且我想將它放在父級別上,因爲PropertyChanged會觸發值本身的字符串值。如何爲實現不同屬性的子類提供驗證?

是否有可能對父類有驗證方法,所以我不必爲每個子類寫一個驗證方法?請注意,每個孩子班的屬性都不相同。

下面是我現在有,在兒童班驗證。

public Parent : INotifyChanged { 
    /// <summary> 
    /// Occurs when a property is changed 
    /// </summary> 
    public event PropertyChangedEventHandler PropertyChanged; 

    /// <summary> 
    /// Raises the <see cref="PropertyChanged"/> for a given 
    /// property. 
    /// </summary> 
    /// <param name="propertyName"></param> 
    protected void OnPropertyChanged(String propertyName) { 
     // Get the hanlder 
     PropertyChangedEventHandler handler = this.PropertyChanged; 

     // Check that the event handler is not null 
     if(null != handler) { 
      // Fire the event 
      handler(this, new PropertyChangedEventArgs(propertyName)); 
     } 
    } 
} 

Child1類:

public Child1 : Parent, IDataErrorInfo { 
private Dictionary<string, string> m_validationErrors = new Dictionary<string, string>(); 

    private void Validate() { 
     this.RemoveError("Child1Description"); 
     if(!Regex.IsMatch(Child1Description, "^([a-zA-Z '-]+)$") && !String.IsNullOrWhiteSpace(Description)) { 
      this.AddError("Child1Description", "Only non-numerics allowed."); 
     } 
    } 

    private void AddError(string columnName, string msg) { 
     if(!m_validationErrors.ContainsKey(columnName)) { 
      m_validationErrors.Add(columnName, msg); 
     } 
    } 

    private void RemoveError(string columnName) { 
     if(m_validationErrors.ContainsKey(columnName)) { 
      m_validationErrors.Remove(columnName); 
     } 
    } 

    public string Error { 
     get { 
      if(m_validationErrors.Count > 0) { 
       return "Field data is invalid."; 
      } 
      else return null; 
     } 
    } 

    public string this[string columnName] { 
     get { 
      if(m_validationErrors.ContainsKey(columnName)) { 
       return m_validationErrors[columnName]; 
      } 
      else { 
       return null; 
      } 
     } 
    } 
    /// <summary> 
    /// Description of the air entity 
    /// </summary> 
    public string Child1Description { 
     get { 
      return Child1description; 
     } 
     set { 
      description = value; 
      Validate(); 
      OnPropertyChanged("Child1Description"); 
     } 
    } 
} 

CHILD2類:

public Child2 : Parent, IDataErrorInfo { 
private Dictionary<string, string> m_validationErrors = new Dictionary<string, string>(); 

    private void Validate() { 
     this.RemoveError("Child2Description"); 
     if(!Regex.IsMatch(Child2Description, "^([a-zA-Z '-]+)$") && !String.IsNullOrWhiteSpace(Description)) { 
      this.AddError("Child2Description", "Only non-numerics allowed."); 
     } 
    } 

    private void AddError(string columnName, string msg) { 
     if(!m_validationErrors.ContainsKey(columnName)) { 
      m_validationErrors.Add(columnName, msg); 
     } 
    } 

    private void RemoveError(string columnName) { 
     if(m_validationErrors.ContainsKey(columnName)) { 
      m_validationErrors.Remove(columnName); 
     } 
    } 

    public string Error { 
     get { 
      if(m_validationErrors.Count > 0) { 
       return "Field data is invalid."; 
      } 
      else return null; 
     } 
    } 

    public string this[string columnName] { 
     get { 
      if(m_validationErrors.ContainsKey(columnName)) { 
       return m_validationErrors[columnName]; 
      } 
      else { 
       return null; 
      } 
     } 
    } 
    /// <summary> 
    /// Description of the air entity 
    /// </summary> 
    public string Child2Description { 
     get { 
      return Child2description; 
     } 
     set { 
      description = value; 
      Validate(); 
      OnPropertyChanged("Child2Description"); 
     } 
    } 
} 
+0

問:是否可以對父類使用驗證方法?答:當然。爲什麼不?你的問題到底是什麼?你可以發佈任何代碼嗎? – paulsm4

+0

@ paulsm4對不起,正試圖清理它。已添加代碼。 –

回答

0

我結束了傳遞屬性名稱,屬性值和我想用來驗證的規則列表。將Validate方法存儲在父代中,因此無論哪個子代使用它,它都會使用它自己的規則,但保留相同的驗證錯誤消息字典。

protected void Validate(string propertyName, string propertyValue, List<ValidRule> validRules) { 
     string temp = propertyValue.ToString(); 
     this.RemoveError(propertyName); 
     if(propertyName.Equals("Description")) { 
      foreach(ValidRule validRule in validRules) { 
       if(!Regex.IsMatch(propertyValue, validRule.Rule) && !String.IsNullOrWhiteSpace(propertyValue)) { 
        this.AddError(propertyName, validRule.ErrorMessage); 
        break; 
       } 
      } 
     } 
} 
0

我不相信你會能夠做到你想要什麼。

在微不足道的情況下,您可能會使其工作。一旦你進入更復雜的類型,我不知道你是通過在父代而不是孩子中進行驗證來節省自己的大量工作。

瑣碎的情況將會是多個孩子擁有相似類型屬性的地方。你可以用同樣的方法強制調用屬性,然後你可以在父屬性中寫一個觸發屬性名稱的驗證規則。然而,你可能會認爲那些屬性應該是父母的一部分,並由孩子繼承。

更復雜的情況是每個孩子的個體特性與其他孩子的特性幾乎沒有相似之處。無論你把驗證碼放在孩子還是父母身上都沒有區別。你必須爲你想驗證的每個單獨屬性編寫驗證碼。

鑑於您的驗證規則將存儲在數據庫中,您可以在父項中編寫一個方法,以允許孩子檢索其屬性的驗證規則。孩子仍然會驗證自己的屬性,但是您將擁有訪問規則的通用代碼。

0

實際上,它確實能夠達到您想要的效果。 以下是我將遵循的步驟來做類似的事情。

  1. 獲得Microsoft企業庫的初學者,因爲您將使用Microsoft.Practices.EnterpriseLibrary.Validation參考。
  2. 創建一個從Validator<T>繼承的驗證類(這是企業庫的一部分)。
  3. 重寫方法DoValidate(T objectToValidate, object currentTarget, string key, ValidationResults validationResults)並且currentTarget是要驗證的對象。您可以從當前目標中提取驗證規則。
  4. 然後,您爲該驗證創建屬性,使其從ValueValidatorAttribute繼承。
  5. 您覆蓋屬性類中的方法DoCreateValidator(Type targetType, Type ownerType, MemberValueAccessBuilder memberValueAccessBuilder, ValidatorFactory validatorFactory)

一旦這些前5個步驟完成這意味着你可以通過屬性要驗證並讓驗證拿起從類使用驗證規則屬性(規則或詞典或規則列表來執行的財產完全是你的選擇)。

下一步是將接口IDataErrorinfo移動到父類,創建一個Validate()方法,它從呼叫Microsoft.Practices.EnterpriseLibrary.Validation.Validation.Validate(this);返回驗證錯誤,他們應該出現的結果。

它取決於你想在哪裏放置方法調用。測試時最簡單的方法是將其放在您擁有的OnPropertyChanged方法中。

相關問題