2016-08-29 12 views
0

私はINotifyPropertyChangedとIDataErrorInfoを実装するバインド可能な基本クラスで作業していますので、WPFにバインドするプロパティを変更通知で書き込んでDataAnnotations検証を使用できるようにしています。この記事へのプロパティゲッターで型を推論できません

賞賛:https://code.msdn.microsoft.com/windowsdesktop/Validation-in-MVVM-using-12dafef3記事は素晴らしいですが、私は臆面もなく

からコピーしてきた、それはので、私は少し物事をクリーンアップしようとしているCallerMemberNameの利点を取ることはありません。

サンプル作成者は、すべてのプライベートプロパティ値を辞書に格納するSetValueメソッドとGetValueメソッドを記述することで、クラス内のプライベートフィールドにプロパティ値を格納するのをスキップできます。著者はこれを行うには4つの機能を使用:

/// <summary> 
    /// Sets the value of a property. 
    /// </summary> 
    /// <typeparam name="T">The type of the property value.</typeparam> 
    /// <param name="propertySelector">Expression tree contains the property definition.</param> 
    /// <param name="value">The property value.</param> 
    protected void SetValue<T>(Expression<Func<T>> propertySelector, T value) 
    { 
     string propertyName = GetPropertyName(propertySelector); 

     SetValue<T>(propertyName, value); 
    } 

    /// <summary> 
    /// Sets the value of a property. 
    /// </summary> 
    /// <typeparam name="T">The type of the property value.</typeparam> 
    /// <param name="propertyName">The name of the property.</param> 
    /// <param name="value">The property value.</param> 
    protected void SetValue<T>(string propertyName, T value) 
    { 
     if (string.IsNullOrEmpty(propertyName)) 
     { 
      throw new ArgumentException("Invalid property name", propertyName); 
     } 

     _values[propertyName] = value; 
     NotifyPropertyChanged(propertyName); 
    } 

    /// <summary> 
    /// Gets the value of a property. 
    /// </summary> 
    /// <typeparam name="T">The type of the property value.</typeparam> 
    /// <param name="propertySelector">Expression tree contains the property definition.</param> 
    /// <returns>The value of the property or default value if not exist.</returns> 
    protected T GetValue<T>(Expression<Func<T>> propertySelector) 
    { 
     string propertyName = GetPropertyName(propertySelector); 

     return GetValue<T>(propertyName); 
    } 

    /// <summary> 
    /// Gets the value of a property. 
    /// </summary> 
    /// <typeparam name="T">The type of the property value.</typeparam> 
    /// <param name="propertyName">The name of the property.</param> 
    /// <returns>The value of the property or default value if not exist.</returns> 
    protected T GetValue<T>(string propertyName) 
    { 
     if (string.IsNullOrEmpty(propertyName)) 
     { 
      throw new ArgumentException("Invalid property name", propertyName); 
     } 

     object value; 
     if (!_values.TryGetValue(propertyName, out value)) 
     { 
      value = default(T); 
      _values.Add(propertyName, value); 
     } 

     return (T)value; 
    } 

私は、次の2つにこれらの4つの機能を交換しています

/// <summary> 
    /// Sets the value of a property. 
    /// </summary> 
    /// <typeparam name="T">The type of the property value.</typeparam> 
    /// <param name="propertyName">The name of the property.</param> 
    /// <param name="value">The property value.</param> 
    protected void SetValue<T>(T value, [CallerMemberName] string propertyName = "") 
    { 
     if (string.IsNullOrEmpty(propertyName)) 
     { 
      throw new ArgumentException("Invalid property name", propertyName); 
     } 

     _values[propertyName] = value; 
     NotifyPropertyChanged(propertyName); 
    } 

    /// <summary> 
    /// Gets the value of a property. 
    /// </summary> 
    /// <typeparam name="T">The type of the property value.</typeparam> 
    /// <param name="propertyName">The name of the property.</param> 
    /// <returns>The value of the property or default value if not exist.</returns> 
    protected T GetValue<T>([CallerMemberName] string propertyName = "") 
    { 
     if (string.IsNullOrEmpty(propertyName)) 
     { 
      throw new ArgumentException("Invalid property name", propertyName); 
     } 

     object value; 
     if (!_values.TryGetValue(propertyName, out value)) 
     { 
      value = default(T); 
      _values.Add(propertyName, value); 
     } 

     return (T)value; 
    } 

私はそれがいくつかの機能を排除し、メソッドを呼び出して簡略化しているため、それが改善だと思います。次のように

本来の機能を使用してプロパティが実装されている:

[Range(1, 100, ErrorMessage = "Age should be between 1 to 100")] 
    public int Age 
    { 
     get { return GetValue(() => Age); } 
     set { SetValue(() => Age, value); } 
    } 

以下に示すように、私は私に同じプロパティを実装したいと思います:

[Range(1, 100, ErrorMessage = "Age should be between 1 to 100")] 
    public int Age 
    { 
     get { return GetValue(); } 
     set { SetValue(value); } 
    } 

唯一の問題は、GetValueメソッドが得られるということです私にエラー:メソッドの

型引数___ GetValueメソッド(文字列)は、」利用状況から推測することはできません。型引数を明示的に指定してみてください。

[Range(1, 100, ErrorMessage = "Age should be between 1 to 100")] 
    public int Age 
    { 
     get { return GetValue<int>(); } 
     set { SetValue(value); } 
    } 

任意のアイデア:

だから私はこのようにそれを実装する必要がありますか?元のコードが型を推論できる理由はわかりませんが、コードはできません。

+0

GetValueメソッド()を返します。 } 'あなたが' get {return GetValue( "Age"); } 'または何かが足りない? –

+0

@SamIam:いいえ、このメソッドは引数の 'CallerMemberName'属性で文字列を取得しますが、あなたはそれを自分で設定しません。 –

+0

ああ、どんな速度でも、コンパイラが 'GetValue(" Age ")'がintを返すことを設計時に認識することを期待するのはちょっとです。 –

答えて

1

あなたはGetValueの返品タイプdynamicを作ることができ、それはエラーなしにプロパティタイプに強制的に戻されます。 {得る `によって

+0

さがCallerMember属性私は。使用できますか? – Eric

+0

@エリック:わかりません。ダイナミックを使うだけでしょうか。 –

+0

@Eric:[ここにリスト](https://msdn.microsoft.com/en-us/library/mt653988.aspx)でそのような何かの欠如は、それはそうなります。 –

関連する問題