2008-08-20 6 views
15

Ceci est probablement mieux montré avec un exemple. J'ai un ENUM avec des attributs:Quelqu'un connaît un moyen rapide d'accéder aux attributs personnalisés sur une valeur enum?

public enum MyEnum { 

    [CustomInfo("This is a custom attrib")] 
    None = 0, 

    [CustomInfo("This is another attrib")] 
    ValueA, 

    [CustomInfo("This has an extra flag", AllowSomething = true)] 
    ValueB, 
} 

Je veux arriver à ces attributs d'une instance:

public CustomInfoAttribute GetInfo(MyEnum enumInput) { 

    Type typeOfEnum = enumInput.GetType(); //this will be typeof(MyEnum) 

    //here is the problem, GetField takes a string 
    // the .ToString() on enums is very slow 
    FieldInfo fi = typeOfEnum.GetField(enumInput.ToString()); 

    //get the attribute from the field 
    return fi.GetCustomAttributes(typeof(CustomInfoAttribute ), false). 
     FirstOrDefault()  //Linq method to get first or null 
     as CustomInfoAttribute; //use as operator to convert 
} 

Comme cela utilise la réflexion, je pense une certaine lenteur, mais il semble désordonné de convertir le ENUM valeur à une chaîne (qui reflète le nom) quand j'en ai déjà une instance.

Est-ce que quelqu'un a un meilleur moyen?

+0

Avez-vous comparé avec 'Enum.GetName()'? –

Répondre

9

C'est probablement le moyen le plus simple.

Un moyen plus rapide serait d'émettre statiquement le code IL en utilisant la méthode dynamique et ILGenerator. Bien que je l'ai seulement utilisé à GetPropertyInfo, mais ne peux pas voir pourquoi vous ne pourriez pas également émettre CustomAttributeInfo.

Pour exemple de code pour émettre un getter d'une propriété

public delegate object FastPropertyGetHandler(object target);  

private static void EmitBoxIfNeeded(ILGenerator ilGenerator, System.Type type) 
{ 
    if (type.IsValueType) 
    { 
     ilGenerator.Emit(OpCodes.Box, type); 
    } 
} 

public static FastPropertyGetHandler GetPropertyGetter(PropertyInfo propInfo) 
{ 
    // generates a dynamic method to generate a FastPropertyGetHandler delegate 
    DynamicMethod dynamicMethod = 
     new DynamicMethod(
      string.Empty, 
      typeof (object), 
      new Type[] { typeof (object) }, 
      propInfo.DeclaringType.Module); 

    ILGenerator ilGenerator = dynamicMethod.GetILGenerator(); 
    // loads the object into the stack 
    ilGenerator.Emit(OpCodes.Ldarg_0); 
    // calls the getter 
    ilGenerator.EmitCall(OpCodes.Callvirt, propInfo.GetGetMethod(), null); 
    // creates code for handling the return value 
    EmitBoxIfNeeded(ilGenerator, propInfo.PropertyType); 
    // returns the value to the caller 
    ilGenerator.Emit(OpCodes.Ret); 
    // converts the DynamicMethod to a FastPropertyGetHandler delegate 
    // to get the property 
    FastPropertyGetHandler getter = 
     (FastPropertyGetHandler) 
     dynamicMethod.CreateDelegate(typeof(FastPropertyGetHandler)); 


    return getter; 
} 
7

Je trouve généralement la réflexion pour être assez rapide aussi longtemps que vous ne prononcez pas dynamiquement les méthodes.
Puisque vous êtes en train de lire les attributs d'une énumération, votre approche devrait fonctionner correctement sans aucun réel impact sur les performances.

Et rappelez-vous que vous devriez généralement essayer de garder les choses simples à comprendre. Sur l'ingénierie cela juste pour gagner quelques ms pourrait ne pas en valoir la peine.

Questions connexes