2008-08-20 18 views
15

Điều này có thể được hiển thị tốt nhất với một ví dụ. Tôi có một enum với các thuộc tính:Bất cứ ai cũng biết một cách nhanh chóng để có được các thuộc tính tùy chỉnh trên một giá trị enum?

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, 
} 

Tôi muốn để có được những thuộc tính từ một ví dụ:

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 
} 

Vì đây là sử dụng phản ánh Tôi mong đợi một số sự chậm chạp, nhưng có vẻ như lộn xộn để chuyển đổi các enum giá trị cho một chuỗi (phản ánh tên) khi tôi đã có một thể hiện của nó.

Có ai có cách nào tốt hơn không?

+0

Bạn đã so sánh với 'Enum.GetName()' chưa? –

Trả lời

9

Đây có lẽ là cách dễ nhất.

Cách nhanh hơn là Statically Emit the IL code sử dụng Dynamic Method và ILGenerator. Mặc dù tôi đã chỉ sử dụng này để GetPropertyInfo, nhưng không thể thấy lý do tại sao bạn không thể phát ra CustomAttributeInfo là tốt.

Ví dụ mã để phát ra một getter từ một tài sản

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; 
} 
7

Tôi thường thấy phản ánh là khá nhanh chóng, miễn là bạn không tự động gọi phương pháp này.
Vì bạn chỉ đọc các thuộc tính của một enum, cách tiếp cận của bạn sẽ hoạt động tốt mà không có bất kỳ hit hiệu suất thực sự nào.

Và hãy nhớ rằng bạn thường nên cố gắng giữ cho mọi thứ đơn giản dễ hiểu. Hơn kỹ thuật này chỉ để đạt được một vài ms có thể không có giá trị nó.