2017-09-21 2 views
2

Vu le code de répéter dans mon projet sous la forme:Extrayez attribut à l'aide des génériques

public static ReasonAttributes GetAttributes(this Reason value) 
{ 
    var type = value.GetType(); 
    var name = Enum.GetName(type, value); 
    if (name == null) return null; 
    var field = type.GetField(name); 
    if (field == null) return null; 
    return Attribute.GetCustomAttribute(field, typeof(ReasonAttributes)) as ReasonAttributes; 
} 

Est-il possible de créer un générique je peux éviter de répéter le code? Le long des lignes de:

public static T GetAttribute<T, T1>(T1 value) 
{ 
    var type = value.GetType(); 
    var name = Enum.GetName(type, value); 
    if (name == null) return default(T); 
    var field = type.GetField(name); 
    if (field == null) return default(T); 
    return Attribute.GetCustomAttribute(field, typeof(T)) as T; 
} 

Je reçois l'erreur sur la ligne de retour:

The type parameter <T> cannot be used with the `as` operator because it does not have a class type constraint nor a `class` constraint. 

Répondre

4

facile, il suffit de mettre une contrainte de type qui dit T doit hériter de Attribute.

public static T GetAttribute<T>(object value) 
    where T : Attribute 
{ 
    var type = value.GetType(); 
    var name = Enum.GetName(type, value); 
    if (name == null) return default(T); 
    var field = type.GetField(name); 
    if (field == null) return default(T); 

    return Attribute.GetCustomAttribute(field, typeof(T)) as T; 
} 

Vous n'avez pas besoin de T1 du tout; vous pouvez appeler GetType() sur n'importe quoi (sauf null bien sûr). Vous n'avez même jamais utilisé T1 dans le corps de la méthode, donc, peu importe le type du paramètre.

where T : class fonctionnerait aussi bien, mais vous pouvez également demander au compilateur de prévenir quelqu'un appelant inconsidérément GetAttribute<String>().

+1

Meilleure réponse que la mienne. Bon travail Monsieur :-) – Wndrr

3

Vous ne devez pas ajouter where T : class à votre définition de méthode afin que votre code sache que T can est une classe et peut être instancié?

public static T GetAttribute<T, T1>(T1 value) where T : class 
{ 
    var type = value.GetType(); 
    var name = Enum.GetName(type, value); 
    if (name == null) return default(T); 
    var field = type.GetField(name); 
    if (field == null) return default(T); 
    return Attribute.GetCustomAttribute(field, typeof(T)) as T; 
}