2013-08-08 16 views
9

コードの量についてお詫びしますが、このように説明する方が簡単です。ジェネリック、列挙型、カスタム属性 - 可能でしょうか?

私は次のようにCustomUserDataが実装されたカスタム属性している:として

public class CustomUserData : Attribute 
{ 
    public CustomUserData(object aUserData) 
    { 
     UserData = aUserData; 
    } 
    public object UserData { get; set; } 
} 

と列挙型の拡張方法:

public static class EnumExtensions 
{ 
    public static TAttribute GetAttribute<TAttribute>(this Enum aValue) where TAttribute : Attribute 
    { 
     Type type = aValue.GetType(); 
     string name = Enum.GetName(type, aValue); 
     return type.GetField(name) 
        .GetCustomAttributes(false) 
        .OfType<TAttribute>() 
        .SingleOrDefault(); 
    } 

    public static object GetCustomUserData(this Enum aValue) 
    { 
     CustomUserData userValue = GetAttribute<CustomUserData>(aValue); 
     return userValue != null ? userValue.UserData : null; 
    } 
} 

私は、/が持つ列挙型をデシリアライズシリアライズするヘルパークラスを持っています

public static class ParameterDisplayModeEnumListHelper 
{ 
    public static List<ParameterDisplayModeEnum> FromDatabase(string aDisplayModeString) 
    { 
     //Default behaviour 
     List<ParameterDisplayModeEnum> result = new List<ParameterDisplayModeEnum>(); 

     //Split the string list into a list of strings 
     List<string> listOfDisplayModes = new List<string>(aDisplayModeString.Split(',')); 

     //Iterate the enum looking for matches in the list 
     foreach (ParameterDisplayModeEnum displayModeEnum in Enum.GetValues(typeof (ParameterDisplayModeEnum))) 
     { 
      if (listOfDisplayModes.FindIndex(item => item == (string)displayModeEnum.GetCustomUserData()) >= 0) 
      { 
       result.Add(displayModeEnum); 
      } 
     } 

     return result; 
    } 

    public static string ToDatabase(List<ParameterDisplayModeEnum> aDisplayModeList) 
    { 
     string result = string.Empty; 

     foreach (ParameterDisplayModeEnum listItem in aDisplayModeList) 
     { 
      if (result != string.Empty) 
       result += ","; 
      result += listItem.GetCustomUserData(); 
     } 

     return result; 
    } 
} 

しかし、それに関連するカスタムデータは次のとおりです。 sが特定にParameterDisplayModeEnumであると私は私のような一般的な持っていることを好むので、シリアライズ/デシリアライゼーションのためにこの方法を処理するために必要な列挙型の束があります。しかし、これは動作しません

public static class EnumListHelper<TEnum> 
{ 
    public static List<TEnum> FromDatabase(string aDisplayModeString) 
    { 
     //Default behaviour 
     List<TEnum> result = new List<TEnum>(); 

     //Split the string list into a list of strings 
     List<string> listOfDisplayModes = new List<string>(aDisplayModeString.Split(',')); 

     //Iterate the enum looking for matches in the list 
     foreach (TEnum displayModeEnum in Enum.GetValues(typeof (TEnum))) 
     { 
      if (listOfDisplayModes.FindIndex(item => item == (string)displayModeEnum.GetCustomUserData()) >= 0) 
      { 
       result.Add(displayModeEnum); 
      } 
     } 

     return result; 
    } 

    public static string ToDatabase(List<TEnum> aDisplayModeList) 
    { 
     string result = string.Empty; 

     foreach (TEnum listItem in aDisplayModeList) 
     { 
      if (result != string.Empty) 
       result += ","; 
      result += listItem.GetCustomUserData(); 
     } 

     return result; 
    } 
} 

をGetCustomUserData()を呼び出すことはできません。助言がありますか?カスタム属性の使用や列挙型の使用を変更することはできません。私は毎回具体的なリストヘルパークラスを書くことなく、シリアライゼーション/デシリアライズを行う一般的な方法を探しています。

すべての提案が高く評価されました。

答えて

2

てみてくださいこれはコード:

public static class EnumListHelper 
{ 
    private static void EnsureIsEnum<TEnum>() 
    { 
     if (!typeof(TEnum).IsEnum) 
      throw new InvalidOperationException(string.Format("The {0} type is not an enum.", typeof(TEnum))); 
    } 

    public static List<TEnum> FromDatabase<TEnum>(string aDisplayModeString) 
     where TEnum : struct 
    { 
     EnsureIsEnum<TEnum>(); 
     //Default behaviour 
     List<TEnum> result = new List<TEnum>(); 

     //Split the string list into a list of strings 
     List<string> listOfDisplayModes = new List<string>(aDisplayModeString.Split(',')); 

     //Iterate the enum looking for matches in the list 
     foreach (Enum displayModeEnum in Enum.GetValues(typeof(TEnum))) 
     { 
      if (listOfDisplayModes.FindIndex(item => item == (string)displayModeEnum.GetCustomUserData()) >= 0) 
      { 
       result.Add((TEnum)(object)displayModeEnum); 
      } 
     } 

     return result; 
    } 

    public static string ToDatabase<TEnum>(List<TEnum> aDisplayModeList) 
     where TEnum : struct 
    { 
     EnsureIsEnum<TEnum>(); 
     string result = string.Empty; 

     foreach (var listItem in aDisplayModeList.OfType<Enum>()) 
     { 
      if (result != string.Empty) 
       result += ","; 
      result += listItem.GetCustomUserData(); 
     } 

     return result; 
    } 
} 

var fromDatabase = EnumListHelper.FromDatabase<TestEnum>("test"); 
EnumListHelper.ToDatabase(fromDatabase); 

UPDATE 0

我々はジェネリックを制限することはできませんので、明確にしますEnumタイプTEnumが列挙型であることを確認し、そうでない場合は例外をスローする必要があります。 我々はTEnumがenumであることを知っている、と我々はTEnum指定する列挙型をキャストするために、このコードを書くことができFromDatabaseメソッドを使用する場合:TEnumが列挙型であることを、我々はまた、知っているToDatabase方法で

result.Add((TEnum)(object)displayModeEnum) 

と私達ができます

aDisplayModeList.OfType<Enum>() 
+0

素晴らしいですし、ちょうど私が達成しようとしていたとしますEnum型にTEnumを変換するには、このコードを記述します。ありがとう。 – TheEdge

+0

ちょうどコードをダンプして、あなたがしたことを説明しないでください。 – CodeCaster

+1

@CodeCaster答えを更新しました。 –

2

理想的には、列挙型にTEnumを制限したいと思いますが、それはあなたが列挙Microsoft
にジェネリックを制限する。しかし、次の試みることができないとして、それはトリックを行う可能性があります動作しません...

if (listOfDisplayModes.FindIndex(item => 
    item == (string)(displayModeEnum as Enum).GetCustomUserData()) >= 0) 
関連する問題