Кто-нибудь знает быстрый способ получить доступ к пользовательским атрибутам по значению enum?

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

Вопрос

Вероятно, лучше всего это показать на примере.У меня есть перечисление с атрибутами:

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

Я хочу получить доступ к этим атрибутам из экземпляра:

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
}

Поскольку при этом используется отражение, я ожидаю некоторой медлительности, но кажется грязным преобразовывать значение enum в строку (которая отражает имя), когда у меня уже есть его экземпляр.

У кого-нибудь есть способ получше?

Это было полезно?

Решение

Это, наверное, самый простой способ.

Более быстрым способом было бы статически выдавать IL-код, используя Dynamic Method и ILGenerator.Хотя я использовал это только для GetPropertyInfo, но не могу понять, почему вы также не могли создать CustomAttributeInfo.

Например, код для получения средства получения из свойства

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

Другие советы

Обычно я нахожу отражение довольно быстрым, если вы не вызываете методы динамически.
Поскольку вы просто читаете атрибуты перечисления, ваш подход должен работать просто отлично, без какого-либо реального снижения производительности.

И помните, что вы, как правило, должны стараться делать вещи простыми для понимания.Переусердствовать с этим только ради того, чтобы выиграть несколько мс, возможно, не стоит.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top