代码之家  ›  专栏  ›  技术社区  ›  Keith

有人知道一种快速获取枚举值自定义属性的方法吗?

  •  21
  • Keith  · 技术社区  · 17 年前

    这可能最好用一个例子来说明。我有一个带有属性的枚举:

    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
    }
    

    由于这是使用反射,我预计会有一些缓慢,但当我已经有一个枚举值的实例时,将枚举值转换为字符串(反映名称)似乎很麻烦。

    有人有更好的办法吗?

    2 回复  |  直到 17 年前
        1
  •  10
  •   von v.    12 年前

    这可能是最简单的方法。

    一种更快的方法是使用动态方法和ILGenerator静态发射IL代码。虽然我只将其用于GetProropertyInfo,但不明白为什么不能同时发出CustomAttributeInfo。

    例如,从属性发出getter的代码

    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;
    }
    
        2
  •  7
  •   Lars Mæhlum    17 年前

    我通常认为,只要不动态调用方法,反射就会非常快。
    由于您只是在读取枚举的属性,因此您的方法应该可以很好地工作,而不会对性能产生任何影响。

    记住,你通常应该尽量让事情简单易懂。仅仅为了获得几毫秒而过度设计可能不值得。