2013-08-08 5 views
9

Entschuldigung für die Menge an Code, aber es ist einfacher, es auf diese Weise zu erklären.Generics, Enums und benutzerdefinierte Attribute - ist das möglich?

ich eine benutzerdefinierte Attribut haben CustomUserData wie folgt umgesetzt:

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

und eine Erweiterungsmethode für Aufzählungen wie:

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; 
    } 
} 

ich dann eine Hilfsklasse, die/eine ENUM serialisiert deserialisiert, der hat Benutzerdefinierte Daten wie folgt zugeordnet:

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; 
    } 
} 

jedoch thi s ist spezifische zu ParameterDisplayModeEnum und ich habe eine Reihe von Aufzählungen, die ich brauche diese Art und Weise für die Serialisierung/Deserialisierung zu behandeln, so würde ich eine generische solche haben möchten wie:

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; 
    } 
} 

aber das wird nicht funktionieren als GetCustomUserData() kann nicht aufgerufen werden. Irgendwelche Vorschläge? Ich kann die Verwendung des benutzerdefinierten Attributs oder die Verwendung der Enums nicht ändern. Ich suche nach einer generischen Art, die Serialisierung/Deserialisierung durchzuführen, ohne jedes Mal eine konkrete Listenhilfsklasse schreiben zu müssen.

Alle Vorschläge geschätzt.

Antwort

2

Try dieser Code:

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

klar sein, weil wir nicht einschränken können Generika Enum sollten wir prüfen, ob der Typ TEnum eine Aufzählung ist und eine Ausnahme werfen, wenn dies nicht der Fall ist. Wenn wir die FromDatabase Methode verwenden, wissen wir, dass TEnum Enum ist, und wir können diesen Code schreiben Sie eine Enum an die angegebene TEnum würfen wir auch

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

im ToDatabase Methode wissen, dass TEnum Enum ist und wir können schreiben diesen Code TEnum zum Enum Typ konvertieren:

aDisplayModeList.OfType<Enum>() 
+0

, der groß ist und nur will ich versuchte, zu erreichen. Vielen Dank. – TheEdge

+0

Bitte geben Sie nicht nur Code ab, erklären Sie, was Sie getan haben. – CodeCaster

+1

@CodeCaster Ich habe die Antwort aktualisiert. –

2

Im Idealfall würde man TENUM auf Enum einschränken wollen, aber das wird nicht funktionieren, da Sie nicht Generika zu Enum Microsoft
beschränken können aber versuchen, folgende, könnte es den Trick ...

if (listOfDisplayModes.FindIndex(item => 
    item == (string)(displayModeEnum as Enum).GetCustomUserData()) >= 0) 
Verwandte Themen