20

私は次の構造を持っており、次の 2 つのクラスの両方の利点を備えたソリューションが必要です。最初のクラスは、文字列と厳密に型指定されたメンバーを使用しています。

public class UserSessionData
{
    private string Get(string key)
    {
        throw new NotImplementedException("TODO: Get from external source");
    }
    private void Set(string key, string value)
    {
        throw new NotImplementedException("TODO: Set in external source");
    }

    public string CustomerNumber {
        get { return Get("CustomerNumber"); }
        set { Set("CustomerNumber", value); }
    }
    public string FirstName {
        get { return Get("FirstName"); }
        set { Set("FirstName", value); }
    }
    public string LastName {
        get { return Get("LastName"); }
        set { Set("LastName", value); }
    }

    // ... a couple of hundreds of these
}

代替手段は、パラメーターを持つGetandSetメソッドであると想像できenumます。2番目のクラスは次のとおりです。

public class UserSessionData
{
    public enum What {
        CustomerNumber, FirstName, LastName, // ...
    }

    public string Get (What what) { return MyExternalSource(what); }
    public string Set (What what, string value) { return MyExternalSource(what); }
}

しかし、クラス #2 のコンシューマー側はきれいではありません。
UserSessionData.Get(UserSessionData.What.CustomerNumber)
最初のクラスと比較してください。UserSessionData.CustomerNumber

私の最初のクラスの例で Get メソッドと Set メソッドを呼び出す厳密に型指定された方法はありますか? 別の言い方をすれば、両方のクラスの利点、つまり、厳密に型指定されたメンバーの保守性と見栄えの良い構文をどのように活用すればよいでしょうか?

4

6 に答える 6

8

T4 テンプレートを使用してクラスを生成できます。T4 テンプレートでは、すべてのプロパティに名前を付けるだけです。列挙型からのリフレクションによってプロパティを取得することもできますが、文字列配列を使用する方が簡単です。

新しいアイテムを追加 -> テキスト テンプレート

<#@ template debug="false" hostspecific="false" language="C#" #>
<#@ output extension=".cs" #>
<# var properties = new string [] {
      "CustomerNumber", // This is where you define the properties
      "FirstName",
      "LastName"
}; #>
class UserSessionData {
<#  
  foreach (string propertyName in properties) 
  { #>
  public string <#= propertyName #>{
    get { return Get("<#= propertyName #>"); }
    set { Set("<#= propertyName #>", value); }
  }
<# } #>
}

詳細情報 @ T4 テキスト テンプレートを使用したデザイン時のコード生成

于 2013-07-09T14:41:41.830 に答える
1

次のようないくつかの拡張メソッドを含む列挙型はどうですか。

// usage:
[TestMethod]
public void example()
{
    UserSessionData.CustomerNumber.Set("cust num");
    Assert.AreEqual("cust num", UserSessionData.CustomerNumber.Get());
}

// implementation:
public enum UserSessionData
{
    CustomerNumber,
    FirstName,
}

public static class UserSessionDataHelper
{
    private static Dictionary<string, string> values = new Dictionary<string, string>();

    private static string GetName(this UserSessionData field)
    {
        return Enum.GetName(typeof(UserSessionData), field);
    }

    public static string Get(this UserSessionData field)
    {
        return values[field.GetName()];
    }

    public static void Set(this UserSessionData field, string value)
    {
        values[field.GetName()] = value;
    }
}
于 2013-07-09T15:15:22.380 に答える
0

.NET 4.0 以降を使用している場合は、 DynamicObjectを使用し、そのTryGetMemberメソッドとTrySetMemberメソッドをオーバーライドして、これを完全に動的にすることができます。ただし、これは強く型付けされません。

于 2013-07-09T14:49:09.440 に答える