1

約 40 個のプロパティを持つクラスがあります (これについては何も言えません。仕様によるものです)。すべてのプロパティには、カスタムの「設定」メソッドがあります。

すべての「設定」メソッドに課さなければならない、少し複雑な検証が 1 つあります。私はすでに検証を別のメソッドに分けています。それを呼び出しましょう

CommonValidate(string PropertyName, string PropertyValue).

以下に示すように、今のところ、個々の「設定」メソッドからこの検証メソッドを呼び出しています。

    public string Property1
    {
        set 
        { 
           this.field1 = value; 
           CommonValidate(Property1, this.field1);
        }
     }

    public DateTime Property2
    {
        set 
        { 
           this.field2 = value.ToString("ddMMyy");; 
           CommonValidate(Property2, this.field2);
        }
     }

     public string Property3
    {
        set 
        { 
           this.field3 = value; 
           CommonValidate(Property3, this.field3);
        }
     }

このようにして、CommonValidate メソッド呼び出しを 40 個の「set」メソッドすべてに貼り付けました。CommonValidate メソッドの引数の数の変更要求がある場合を想像してみてください。

これをより良いモードに変更できる他の方法はありますか?

4

2 に答える 2

1

リフレクションを使用して、プロパティの名前と新しい値を渡す関数を作成できます。検証を行ってから、値を使用して通常の設定を実行します。リフレクションは速度に関しては効率的ではありませんが、コードの再利用には優れています。いくつかの診断を行って、失われた時間が許容範囲内であることを確認してください。

void ValidateAndSet(string propName, object newValue){
    foreach(var prop in propsClass.GetType().GetProperties().Where(p => p.Name == propName))
    {
        if(CommonValidate(prop, newValue))
            prop.GetSetMethod().Invoke(propsClass, new object[] { newValue});
        return; // Only one anyways
    }
    Logger.Log("Failed to find the property '{0}' to set '{1}'", propName, newValue);
}

propsClass は、プロパティが含まれるクラス オブジェクトです。クラス内でこれを行うか、別のパラメーターとして関数に渡すことができます。

于 2013-08-13T12:06:36.287 に答える
0

誰かがすでに動的クラスについて言及していますが、私はそれらに精通していませんが、簡単に読むと、問題に対してかなり魅力的に聞こえます。

ただし、そのルートに行かない場合は、 での文字列の使用を変更しCommonValidate、代わりに を使用しますSystem.Linq.Expression

次のように書き直します。

static void CommonValidate<T>(Expression<Func<MyClass, T>> propertySelector, T newValue) //replace MyClass with name of current class
{
    MemberExpression memberExpression = propertySelector.Body as MemberExpression;
    if (memberExpression == null)
        throw new ArgumentException("propertySelector")

    string propertyName = MemberExpression.Member.Name;

    //validation code, e.g.

    CommonValidate(propertyName, newValue.ToString())
}

次に、セッターは次のようになります

public string Property1
{
    set 
    { 
       this.field1 = value; 
       CommonValidate(c => c.Property1, value);
    }
 }

これの利点は、クラスのプロパティの名前を変更すると、CommonValidate呼び出しを変更しないとコンパイル時エラーになることです。このルートに行く場合は、同様のものを使用して検証を設定する必要があります。コンストラクターがどこかにデータを入力していると想定しています。代わりに、上記Dictionary<string, Func<string, bool>の新しいコードと同様のコードを使用してCommonValidate、プロパティ名キーを取得します。

于 2013-08-13T12:50:34.397 に答える