2013-12-10 13 views
6

重労働の束を行うデータベースオブジェクトクラスがあります。その後、そのオブジェクトを拡張し、実際のオブジェクトやフィールドを表すクラスを変更します。C#設定されているプロパティの名前を取得する方法

public class MyObject : DatabaseObject 
{ 
    public string FieldX 
    { 
     get { return GetValue<string>("FieldX"); } 
     set { SetValue<string>("FieldX", value); } 
    } 

    public int FieldY 
    { 
     get { return GetValue<int>("FieldY"); } 
     set { SetValue<int>("FieldY", value); } 
    } 
} 

public class DatabaseObject 
{ 
    public T GetValue<T>(string FieldName) 
    { 
     // Code that actually gets the right value 
    } 

    public void SetValue<T>(string FieldName, T value) 
    { 
     // Code that actually sets the value in the right place 
    } 
} 

このようにして、後でMyObjectをインスタンス化し、コードでプロパティを設定することができます。アイデアは、より簡単でメンテナンス可能なコードを生成することです。

実際にはうまくいきます。しかし、私はMyObjectのコードがかなり繰り返していることに気付いています。例えば、FieldXでは、get/set内に "string"型を指定し、get/setにもプロパティ名 "FieldX"を指定する必要があります。

繰り返しを減らすためにコードをさらに単純化する方法があるのだろうかと思います。

私はリフレクションを使用することができます知っている:

MethodBase.GetCurrentMethod().Name.Substring(4) 

...取得/設定は、プロパティ名を取得するために呼び出し、私はセットを実行するときに値の型を取得するにはgettype()を使用することができます内側に、しかし理想的には、GetValue/SetValueの基本メソッド内から元のプロパティ名を取得したい(スタックトレースを解析するのが理想的ではない)。

理想的には、私はこのような何かを探しています:

public string FieldX 
    { 
     get { return GetValue(); } 
     set { SetValue(value); } 
    } 

    public int FieldY 
    { 
     get { return GetValue(); } 
     set { SetValue(value); } 
    } 

任意の考え?

答えて

3

これはあなたが探しているよりも少し長くなりますが、使用することもできます(強く型付けされたラムダ式を使用)。

public class MyObject : DatabaseObject 
{ 
    public string FieldX 
    { 
     get { return GetValue(() => FieldX); } 
     set { SetValue(() => FieldX, value); } 
    } 

    public int FieldY 
    { 
     get { return GetValue(() => FieldY); } 
     set { SetValue(() => FieldY, value); } 
    } 
} 

public class DatabaseObject 
{ 
    public T GetValue<T>(Expression<Func<T>> field) 
    { 
     string fieldName = GetFieldName(field); 
     // Code that actually gets the right value 
    } 

    public void SetValue<T>(Expression<Func<T>> field, T value) 
    { 
     string fieldName = GetFieldName(field); 
     // Code that actually sets the value in the right place 
    } 

    private static string GetFieldName<T>(Expression<Func<T>> field) 
    { 
     return ((MemberExpression)field.Body).Member.Name; 
    } 
} 
7

C#5.0は、デフォルトパラメータの[CallerMemberName]属性を使用してこれをサポートしています。このような何か:

public static object GetValue([CallerMemberName] string caller = "") 
{ 
    Trace.WriteLine("Called by: " + caller); 
    return null; 
} 

などを使用することになります。これは、自動的に発信者の名前に基づいてGetValueのパラメータを指定するコンパイラで動作します

public string FieldX 
{ 
    get { return (string)GetValue(); } 
} 

この機能の詳細については、in MSDNをご覧ください。

おそらくGetValueを汎用品にすることができます。そのため、お客様のプロパティでGetValue<string>()のように使用できます。

+0

私は正しい答えとして両方のマークを付けることはできません。私は、上記のC#5.0の答えは正しい長期的なアプローチだと思うが、プロジェクトの要件は残念ながら今日この使用を制限しているので、私は以下の答えに落ちなければならない。 – jhilgeman