2012-03-07 60 views
24

我正在構建一個應用程序,可以大量使用Enum來定製數據。本質上,一個對象存儲在數據庫中,大約有28個獨立的屬性。每個屬性都是從SQL直接轉換爲Enum的雙字符字段。Enums的自定義屬性是否危險?

不幸的是,我還需要將這些值轉換成兩個不同的人類可讀值。一個用於數據表上的圖例,另一個用於CSS類來在Web應用程序前端設計圖像。

爲此,我設置了兩個自定義屬性,並在必要時將它們應用於Enum。例如:

自定義屬性接口

public interface IAttribute<T> 
{ 
    T Value { get; } 
} 

實施例自定義屬性

public sealed class AbbreviationAttribute: Attribute, IAttribute<string> 
{ 
    private readonly string value; 

    public AbbreviationAttribute(string value) 
    { 
     this.value = value; 
    } 

    public string Value 
    { 
     get { return this.value; } 
    } 
} 

方法可以檢索自定義從Enum

public static R GetAttributeValue<T, R>(IConvertible @enum) 
{ 
    R attributeValue = default(R); 

    if (@enum != null) 
    { 
     FieldInfo fi = @enum.GetType().GetField(@enum.ToString()); 

     if (fi != null) 
     { 
      T[] attributes = fi.GetCustomAttributes(typeof(T), false) as T[]; 

      if (attributes != null && attributes.Length > 0) 
      { 
       IAttribute<R> attribute = attributes[0] as IAttribute<R>; 

       if (attribute != null) 
       { 
        attributeValue = attribute.Value; 
       } 
      } 
     } 
    } 

    return attributeValue; 
} 
屬性

Enum使用這種模式

public enum Download 
{ 
    [Abbreviation("check")] 
    [Description("Certified")] 
    C = 1, 

    [Abbreviation("no-formal")] 
    [Description("No formal certification")] 
    NF = 2, 

    [Abbreviation("cert-prob")] 
    [Description("Certified with potential problems")] 
    CP = 3 
} 

兩個AbbreviationDescription是實現IAttribute<T>自定義屬性。我的實際Enum有11個可能的值,正如我之前提到的,它在我的自定義對象中的28個獨立屬性中使用。使用自定義屬性似乎是來回映射這些信息的最佳方式。

現在對於這個問題,這是完成這個最好的方法嗎?我在數據庫中存儲Enum值(上面代碼段中的「C」,「NF」或「CP」),但我需要我的代碼中的縮寫和說明的值。另外,我懷疑這將是我需要的最後一組自定義屬性。

在我繼續前進這種模式之前...... 是否是正確的做事方式?我寧願現在用這種方法解決潛在的問題,而不是必須稍後跟蹤和重構。

+2

我可以看到一些本地化問題 – asawyer 2012-03-07 16:45:05

+0

好點。不過,我可能會修改'IAttribute'來支持gettext風格的本地化設置。我更關心我可能不知道的可伸縮性,性能和最佳實踐。 – EAMann 2012-03-07 16:48:11

+0

'GetAttributeValue'不是與前面的描述文字相反的擴展方法。 – 2012-03-07 16:57:27

回答

13

這與我使用的方法相同。一個缺點是序列化。自定義屬性值不會序列化。

我喜歡在數據庫方法的自定義屬性的方法,因爲它關係的屬性數據正確的枚舉,而不必使用查找表或類等

+1

另一個缺點是,如果描述的字符變化很大,則必須完全重新部署應用程序 – eouw0o83hf 2012-03-07 17:54:23

+1

@ eouw0o83hf:true。通過最近的部署選項(又名ClickOnce)緩解,但你是正確的。我的大多數應用程序往往是網絡或事件,在部署週期之間有很長時間,其中很多其他事情會發生變化,因此更新幾個描述並不是什麼大不了的事情。 – 2012-03-07 17:57:56

1

你可以改變數據庫嗎?我認爲最好的選擇是製作一個或多個表格來存放枚舉和外鍵的主要對象的可能值(而不是使用char代碼 - 這使得它更容易並且使你的DB標準化) 。給列表一個AbbreviationDescription列,然後將它們拉入並通過它們的鍵引用它們,如果查找速度很慢,則將它們緩存。

有一件事情對於這些屬性來說是危險的,如果任何這些字符串都必須更改,那麼這是完全重新部署應用程序。如果您將它們設置爲數據庫值,則可以使用簡單的UPDATE來更改它們。

2

我可能會建立一個哈希表和這是一個特殊類型的東西。您可能因某種原因已經放棄了這個想法,但這裏是我不知道應用程序的具體細節。

class SpecialType { 
    // include the fields and all attributes that you need to reference, ToString method for debugging, and any serialization you need 
    public string foo { get; set; } 
    public string bar { get; set; } 
    public ToString() { return "SpecialType with foo '" + foo + "' and bar '" + bar + "'"; } 
} 

Dictionary<int, SpecialType> myDict = new Dictionary<int, SpecialType> { 
    { 1, new SpecialType { foo = "XA1B2", bar = "XC3D4" } }, 
    { 2, new SpecialType { foo = "ZA1B2", bar = "ZC3D4" } }, 
    { 3, new SpecialType { foo = "YA1B2", bar = "YC3D4" } }, 
} 

然後,我可以輕鬆地在整數我的其他類以節省內存,找出一個特定的值是有效的通過檢查詞典的按鍵,所有爵士樂存在。如果你最終要使用WPF或者讀/寫磁盤,那麼做數據綁定可能會容易得多。