这可能是最好的例子.我有一个属性的枚举:
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 }
由于这是使用反射我希望有些慢,但是当我已经拥有它的实例时,将枚举值转换为字符串(它反映了名称)似乎很麻烦.
有没有人有更好的方法?
这可能是最简单的方法.
更快的方法是使用Dynamic Method和ILGenerator静态发出IL代码.虽然我只是将它用于GetPropertyInfo,但是看不出为什么你也不能发出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; }
只要你不动态调用方法,我通常会发现反射很快.
由于您只是阅读枚举的属性,因此您的方法应该可以正常工作而不会有任何真正的性能损失.
请记住,您通常应该尝试让事情变得简单易懂.过度设计这只是为了获得几毫秒可能不值得.