Wer weiß einen schnellen Weg, um benutzerdefinierte Attribute für ein enum-Wert?
-
09-06-2019 - |
Frage
Dies ist wahrscheinlich am besten mit einem Beispiel.Ich habe ein enum mit Parametern:
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,
}
Ich will diese Attribute von Instanz:
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
}
Als diese ist die Verwendung von reflektion ich erwarten, dass einige Langsamkeit, aber es scheint chaotisch zu konvertieren, die enum-Wert in einen string (der Ausdruck der name), wenn ich bereits eine Instanz von es.
Hat jemand einen besseren Weg?
Lösung
Dies ist wahrscheinlich der einfachste Weg.
Ein schneller Weg sein würde, zu Statisch Strahlen der IL-code über Dynamische Methode und ILGenerator.Zwar habe ich nur diese verwendet, um GetPropertyInfo, aber kann nicht sehen, warum Sie konnte nicht emittieren CustomAttributeInfo als gut.
Für den Beispiel-code zu emittieren eine getter-Eigenschaft von einem
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;
}
Andere Tipps
Ich find allgemein Reflexion, ziemlich schnell, wie lange, wie Sie nicht dynamisch aufrufen von Methoden.
Da Sie gerade Lesen der Attribute eines enum, Ihr Ansatz sollte gut funktionieren, ohne wirkliche Leistung Treffer.
Und denken Sie daran, dass Sie grundsätzlich versuchen sollten, die Dinge einfach zu verstehen.Über engineering, nur um zu gewinnen ein paar ms könnte es sich nicht lohnen.