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");
        }
    }
}
4

3 に答える 3

0

実際、それはあなたがそれを起こさせたいと思っている方法ではありません。以下は、私が同様のことをするために従うステップです。

  1. Microsoft.Practices.EnterpriseLibrary.Validationリファレンスを使用するので、初心者向けのMicrosoftエンタープライズライブラリを入手してください。
  2. から継承する検証クラスを作成しますValidator<T>(これはEnterpriseライブラリの一部です)。
  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あなたが持っている方法にそれを置くことです。

于 2012-09-09T19:22:15.690 に答える
0

あなたがやりたいことができるとは思えません。

些細なケースでは、それを機能させることができるかもしれません。より複雑な型に移行すると、子ではなく親で検証を行うことで多くの労力を節約できるかどうかはわかりません。

些細なケースは、複数の子が同様のタイプのプロパティを持つ場合です。同じ方法でプロパティを強制的に呼び出すことができ、プロパティの名前でトリガーされる検証ルールを親内に記述できます。ただし、これらのプロパティは親の一部であり、子に継承される必要があると主張することもできます。

より複雑なケースは、各子の個々のプロパティで、他の子のプロパティとほとんどまたはまったく類似していません。検証コードを子または親のどちらに配置しても違いはありません。検証する個々のプロパティごとに検証コードを記述する必要があります。

検証ルールが DB に格納される場合、親にメソッドを記述して、子がプロパティの検証ルールを取得できるようにすることができます。子は引き続き独自のプロパティを検証しますが、ルールにアクセスするための共通のコードが必要になります。

于 2012-09-07T20:18:57.217 に答える
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;
                }
           }
      }
 }
于 2012-09-20T14:38:20.513 に答える