2012-09-07 34 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方法中。

相关问题