2009-02-20 30 views

Trả lời

25

Đây là những gì tôi đã kết thúc đi với, tôi không nhìn thấy giá trị trong việc thêm một tùy chỉnh thuộc tính lớp để tổ chức một khóa tài nguyên và sau đó tìm kiếm trong các tệp tài nguyên - tại sao không chỉ sử dụng giá trị tên tệp enums + làm khóa tài nguyên?

using System; 
using System.Resources; 
using System.Reflection; 

public class MyClass 
{ 
    enum SomeEnum {Small,Large}; 

    private ResourceManager _resources = new ResourceManager("MyClass.myResources", 
          System.Reflection.Assembly.GetExecutingAssembly());  

    public string EnumDescription(Enum enumerator) 
    {  
    string rk = String.Format("{0}.{1}",enumerator.GetType(),enumerator); 
    string localizedDescription = _resources.GetString(rk); 

    if (localizedDescription == null) 
     { 
     // A localized string was not found so you can either just return 
     // the enums value - most likely readable and a good fallback. 
     return enumerator.ToString(); 

     // Or you can return the full resourceKey which will be helpful when 
     // editing the resource files(e.g. MyClass+SomeEnum.Small) 
     // return resourceKey; 
     } 
    else 
     return localizedDescription; 
    } 


    void SomeRoutine() 
    { 
    // Looks in resource file for a string matching the key 
    // "MyClass+SomeEnum.Large" 
    string s1 = EnumDescription(SomeEnum.Large);  
    } 
} 
+4

một Enum không phải là một điều tra viên, phải không? Đó là một loại liệt kê, nhưng một điều tra là một cái gì đó khá khác nhau tôi tin rằng ... – Svish

+4

Sử dụng C# 3.5 bạn có thể làm cho phương pháp đó một phương pháp mở rộng để sau đó bạn có thể sử dụng SomeEnum.Large.EnumDescription(); –

+2

Chỉ cần vấp phải câu hỏi này khi tìm kiếm một vấn đề khác. Tôi chỉ nhắc nhở rằng việc sử dụng tên và tên thành viên làm cho ứng dụng của bạn khó khăn hơn để làm xáo trộn (bạn phải loại trừ khai báo hợp lý khỏi quá trình này). –

8

có một giải pháp dễ dàng: sử dụng thuộc tính LocalizedDescription để chuyển khóa tài nguyên.

[Serializable] 
    public class LocalizableDescriptionAttribute:DescriptionAttribute 
    { 
     public LocalizableDescriptionAttribute(string resourceKey) 
      :base(Resources.ResourceManager.GetString(resourceKey)) 
     { } 

    } 
+0

Tôi không chắc chắn điều này giúp bạn hơn bằng cách sử dụng enums loại tên đầy đủ (namespace.enumname.value) là resourcekey.Nó có vẻ giống như một bước không cần thiết thêm (sử dụng sự phản chiếu để lấy LocalizableDescriptionAttribute) qua việc đi đến resourceManager - tôi đang thiếu gì? – Ryan

+0

Tôi nghĩ chúng ta có một sự hiểu lầm. Tôi sử dụng thuộc tính của mình để bản địa hóa mô tả giá trị enum. Tôi đoán bạn đang nói về việc địa phương hóa enums nhưng không phải là giá trị của họ. – Valentin

+0

Bạn không thể trang trí giá trị enum với thuộc tính Mô tả và chuyển một khóa tài nguyên. – Valentin

0

Xem ví dụ bàn của tôi trong câu hỏi này: bản đồ

Localisation/I18n of database data in LINQ to SQL

Tình trạng loại bảng để liệt kê các giá trị. Lợi ích thực sự ở đây là bạn có thể có bản địa hóa trong báo cáo và trên các ứng dụng của mình và chỉ định ID bên ngoài để tích hợp với bên thứ ba không muốn giá trị nội bộ của bạn v.v.

+0

Phương pháp tốt cho các ứng dụng trung tâm db, nhưng thực sự quá mức cần thiết cho nhu cầu của tôi. – Ryan

0

Bạn không thể có nhiều System.ComponentModel.DescriptionAttribute được áp dụng (vì vậy tùy chọn đó đã hết).

Vì vậy, thêm mức độ gián tiếp, mô tả giữ tên tài nguyên và sau đó sử dụng hỗ trợ bản địa hóa trong tài nguyên. Rõ ràng người dùng của enum sẽ cần phải gọi phương thức trợ giúp của bạn để làm điều này.

+0

Đây là những gì Valentin Vasiliev đề xuất nhưng không cần sử dụng phương pháp trợ giúp - cũng áp dụng cùng một bình luận. – Ryan

3

Một cách tôi đã làm một lần, là thêm một phương thức kéo dài trong cùng một không gian tên như một enum, trả về một chuỗi. Trong trường hợp của tôi nó đã được hardcoded, nhưng sẽ không có vấn đề nhận được chúng từ một tập tin tài nguyên.

public static string Describe(this SomeEnum e) 
    { 
     switch(e) 
     { 
      SomeEnum.A: 
       return "Some text from resourcefile"; 
      SomeEnum.B: 
       return "Some other text from resourcefile"; 
      ...: 
       return ...; 
     } 
    } 

Có lẽ không phải là một giải pháp cực kỳ trơn tru hay ưa thích, nhưng nó hoạt động =)

+0

+ 1 để sử dụng phương pháp mở rộng ... mặc dù tôi muốn sử dụng tên loại đủ điều kiện của enum làm khóa tài nguyên (xem Ryans answer) –

+0

@ SDX2000: Vâng, đó có thể là một cách thay thế rất tốt để nhận các chuỗi . – Svish

23

Giải pháp của tôi, sử dụng có nguồn gốc thuộc tính decription: khai

public class LocalizedEnumAttribute : DescriptionAttribute 
{ 
    private PropertyInfo _nameProperty; 
    private Type _resourceType; 

    public LocalizedEnumAttribute(string displayNameKey) 
     : base(displayNameKey) 
    { 

    } 

    public Type NameResourceType 
    { 
     get 
     { 
      return _resourceType; 
     } 
     set 
     { 
      _resourceType = value; 

      _nameProperty = _resourceType.GetProperty(this.Description, BindingFlags.Static | BindingFlags.Public); 
     } 
    } 

    public override string Description 
    { 
     get 
     { 
      //check if nameProperty is null and return original display name value 
      if (_nameProperty == null) 
      { 
       return base.Description; 
      } 

      return (string)_nameProperty.GetValue(_nameProperty.DeclaringType, null); 
     } 
    } 
} 

public static class EnumExtender 
{ 
    public static string GetLocalizedDescription(this Enum @enum) 
    { 
     if (@enum == null) 
      return null; 

     string description = @enum.ToString(); 

     FieldInfo fieldInfo = @enum.GetType().GetField(description); 
     DescriptionAttribute[] attributes = (DescriptionAttribute[])fieldInfo.GetCustomAttributes(typeof(DescriptionAttribute), false); 

     if (attributes.Any()) 
      return attributes[0].Description; 

     return description; 
    } 
} 

Các Enum

public enum MyEnum 
{ 
    [LocalizedEnum("ResourceName", NameResourceType = typeof(ResourceType))] 
    Test = 0 
} 

Sau đó gọi MyEnumInstance.GetLocalizedDescription()

+0

Needs BindingFlags.NonPublic và cần truy cập base.Description trong NameResourceType.set. Xem câu trả lời của tôi cho lá cờ enum hỗ trợ. – kerem

+0

Điều này có vẻ tái sử dụng nhiều hơn với tôi sau đó là giải pháp khác. Cảm ơn – Peter

+0

Tôi đã phải thay đổi 'NameResourceType' thành' typeof (Resource) 'để làm việc này. Cảm ơn! – pizycki

1

Thay thế phương thức @ nairik bằng các phương thức sau để thêm hỗ trợ cho cờ enums.

public static string GetLocalizedDescription(this Enum @enum) 
{ 
    if (@enum == null) 
     return null; 

    StringBuilder sbRet = new StringBuilder(); 

    string description = @enum.ToString(); 

    var fields = description.Split(new char[] { ',', ' ' }, StringSplitOptions.RemoveEmptyEntries); 

    foreach (var field in fields) 
    { 
     FieldInfo fieldInfo = @enum.GetType().GetField(field); 
     DescriptionAttribute[] attributes = (DescriptionAttribute[])fieldInfo.GetCustomAttributes(typeof(DescriptionAttribute), false); 

     if (attributes.Any()) 
      sbRet.AppendFormat("{0}, ", attributes[0].Description); 
     else 
      sbRet.AppendFormat("{0}, ", field); 
    } 

    if (sbRet.Length > 2) 
     sbRet.Remove(sbRet.Length - 2, 2); 

    return sbRet.ToString(); 
} 

và thay thế NameResourceType trong các thuộc tính:

public Type NameResourceType 
{ 
    get 
    { 
     return _resourceType; 
    } 
    set 
    { 
     _resourceType = value; 

     _nameProperty = _resourceType.GetProperty(base.Description, BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); 
    } 
} 
Các vấn đề liên quan