هل يعرف أحد طريقة سريعة للوصول إلى السمات المخصصة لقيمة التعداد؟
-
09-06-2019 - |
سؤال
ربما يكون من الأفضل إظهار ذلك بمثال.لدي تعداد مع السمات:
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
}
نظرًا لأن هذا يستخدم الانعكاس، أتوقع بعض البطء، ولكن يبدو أنه من الصعب تحويل قيمة التعداد إلى سلسلة (والتي تعكس الاسم) عندما يكون لدي مثيل لها بالفعل.
هل لدى أي شخص طريقة أفضل؟
المحلول
ربما تكون هذه هي الطريقة الأسهل.
تتمثل الطريقة الأسرع في إصدار كود IL بشكل ثابت باستخدام الطريقة الديناميكية وILGenerator.على الرغم من أنني استخدمت هذا فقط لـ 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;
}
نصائح أخرى
أجد عمومًا أن الانعكاس سريع جدًا طالما أنك لا تستدعي الأساليب ديناميكيًا.
نظرًا لأنك تقرأ للتو سمات التعداد، فيجب أن يعمل أسلوبك بشكل جيد دون أي نتيجة حقيقية للأداء.
وتذكر أنه يجب عليك عمومًا أن تحاول إبقاء الأمور بسيطة بحيث يسهل فهمها.الإفراط في هندسة هذا فقط للحصول على بضع مللي ثانية قد لا يستحق كل هذا العناء.