C# 任何人都知道一种快速获取枚举值上的自定义属性的方法吗?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/17772/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Anyone know a quick way to get to custom attributes on an enum value?
提问by Keith
This is probably best shown with an example. I have an enum with attributes:
这可能最好用一个例子来说明。我有一个带有属性的枚举:
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,
}
I want to get to those attributes from an 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
}
As this is using reflection I expect some slowness, but it seems messy to convert the enum value to a string (which reflects the name) when I already have an instance of it.
由于这是使用反射,我预计会有些缓慢,但是当我已经有了它的实例时,将枚举值转换为字符串(反映名称)似乎很麻烦。
Does anyone have a better way?
有没有人有更好的方法?
采纳答案by JamesSugrue
This is probably the easiest way.
这可能是最简单的方法。
A quicker way would be to Statically Emit the IL code using Dynamic Method and ILGenerator. Although I've only used this to GetPropertyInfo, but can't see why you couldn't emit CustomAttributeInfo as well.
一种更快的方法是使用动态方法和 ILGenerator 静态发出 IL 代码。虽然我只将它用于 GetPropertyInfo,但不明白为什么您也不能发出 CustomAttributeInfo。
For example code to emit a getter from a property
例如从属性发出 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;
}
回答by Lars M?hlum
I generally find reflection to be quite speedy as long as you don't dynamically invoke methods.
Since you are just reading the Attributes of an enum, your approach should work just fine without any real performance hit.
只要您不动态调用方法,我通常会发现反射非常快。
由于您只是在阅读枚举的属性,因此您的方法应该可以正常工作而不会影响任何实际性能。
And remember that you generally should try to keep things simple to understand. Over engineering this just to gain a few ms might not be worth it.
请记住,您通常应该尽量使事情简单易懂。仅仅为了获得几毫秒而过度设计这可能不值得。