Quelqu'un connaît-il un moyen rapide d'accéder aux attributs personnalisés sur une valeur enum ?

StackOverflow https://stackoverflow.com/questions/17772

Question

Ceci est probablement mieux illustré par un exemple.J'ai une énumération avec des attributs :

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 souhaite accéder à ces attributs à partir 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 m'attends à une certaine lenteur, mais il semble compliqué de convertir la valeur enum en une chaîne (qui reflète le nom) alors que j'en ai déjà une instance.

Quelqu'un a-t-il un meilleur moyen ?

Était-ce utile?

La solution

C'est probablement le moyen le plus simple.

Un moyen plus rapide serait d'émettre statiquement le code IL à l'aide de la méthode dynamique et d'ILGenerator.Bien que je ne l'ai utilisé que pour GetPropertyInfo, je ne vois pas pourquoi vous ne pouvez pas également émettre CustomAttributeInfo.

Par exemple du code pour émettre un getter à partir 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;
}

Autres conseils

Je trouve généralement que la réflexion est assez rapide tant que vous n'invoquez pas de méthodes dynamiquement.
Puisque vous lisez simplement les attributs d'une énumération, votre approche devrait fonctionner correctement sans réelle incidence sur les performances.

Et rappelez-vous que vous devriez généralement essayer de garder les choses simples à comprendre.Au cours de l'ingénierie, cela ne vaut peut-être pas la peine de gagner quelques ms.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top