2009-10-21 66 views
1

我正在C#中創建一個網絡聊天客戶端作爲一個副項目。除了簡單的文本消息外,我還有斜槓前綴的命令可以輸入到輸入文本框中。我使用了一種模塊化方法,通過創建一個包含所有各種命令的枚舉,然後使用屬性裝飾這些命令。C#屬性 - 數組還是重複?

屬性指定可以輸入什麼斜線前綴的命令來觸發命令,以及到主命令標識符和命令的使用任何別名。

實施例:當我嘗試以允許多個別名到主命令

public enum CommandType : byte 
{ 
    [PrimaryIdentifier("file"), 
    AdditionalIdentifier("f"), 
    CommandUsage("[<recipient>] [<filelocation>]")] 
    FileTransferInitiation, 

    [PrimaryIdentifier("accept"), 
    AdditionalIdentifier("a")] 
    AcceptFileTransfer, 

    // ... 
} 

我的問題出現了。我嘗試過這兩種方法:允許重複AdditionalIdentifier屬性,或者通過在AdditionalIdentifier中設置構造函數參數params string[]

與前者一樣,我通過裝飾屬性類AttributeUsage並將AllowMultiple設置爲true來實現它。雖然這的確能夠達到我所期望的效果,但我覺得,除了其他屬性之外,它可能會非常快地產生幾行別名。

後者也適用,但是,它所產生的compiler warning CS3016,並說這種做法是不符合CLS。顯然,這並不一定會阻止我繼續使用它,但我已經學會了將警告視爲錯誤。

我的實際問題是我應該忽略重複的反對意見,然後繼續使用它們,或者是否有其他解決方案可以使用?

謝謝。

回答

1

個人而言,我會去的方法的AllowMultiple:我不認爲「噪音」將是太大的問題,除非你真的有每個命令標識符的卡車。但是,如果你不喜歡這樣,想留符合CLS,另一個解決辦法是爲AdditionalIdentifierAttribute提供重載的構造函數:

public AdditionalIdentifierAttribute(string id) { ... } 
public AdditionalIdentifierAttribute(string id1, string id2) { ... } 
public AdditionalIdentifierAttribute(string id1, string id2, string id3) { ... } 

缺點是,這並不限制你標識符的預定數量。

這就是說,CLS遵從真的只有一個主要的考慮因素,如果你正在建設一個圖書館,其他人可能使用(具體爲其他語言)。如果此類型或庫在應用程序內部,則忽略CLS合規性警告是合理的。

編輯:進一步思考這個問題,你對這些枚舉有很多屬性。您可能需要考慮創建一個抽象的Command類,並將標識符,用法等作爲該類的屬性公開;然後派生出具體類型的Command,從那些屬性返回適當的值。這也可能允許您將處理邏輯移動到那些Command對象中,而不是打開枚舉值。

+0

我想你是對的。另一種方法將是您的多構造函數方法,並同時使用AllowMultiple,從而實現更大的靈活性。謝謝! – mgbowen 2009-10-21 22:08:32

2

爲什麼不能有一個具有多個屬性的屬性?讓別名的屬性採用逗號分隔的列表。這是他們在MVC中爲AuthorizeAttribute for Roles所採取的方法。在內部,該屬性將字符串解析爲一個數組,以便在屬性類中使用,但它允許您輕鬆設置配置。

public class IdentifierAttribute 
{ 
    public string Name { get; set; } 
    public string Usage { get; set; } 

    private string[] aliasArray; 
    private string aliases; 
    public string Aliases 
    { 
     get { return this.aliases; } 
     set 
     { 
      this.aliases = value; 
      this.aliasArray = value.Split(',').Trim(); 
     } 
    } 
} 

然後使用它像:

public enum CommandType : byte 
{ 
    [Identifer(Name = "file", Aliases = "f", Usage = "...")] 
    FileTransferType, 

    ... 
} 
+0

謝謝你提出這個建議,我完全忘記了這種可能性!這應該減少類和裝飾的數量:)。如果重複的次數確實會成爲問題,我想我會使用這種方法。 – mgbowen 2009-10-21 22:10:35

0

另一種方法是將有屬性需要字符串作爲構造函數的參數數組 - 這樣,你得到的編譯器解析數組你(在多一點GOOP爲代價施加時的屬性),因此:

[Identifiers(new string[] {"Bill", "Ben", "Ted"})] 

使用這樣的技術看起來像實施&的快速「N髒示例這樣的:

using System; 
using System.Collections.ObjectModel; 
namespace ConsoleApplication1 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      SomeClass.TellMeAboutYourself(); 
     } 
    } 
    public class Identifiers : Attribute 
    { 
     private string[] names; 
     public Identifiers(string[] someNames) 
     { 
      names = someNames; 
     } 
     public ReadOnlyCollection<string> Names { get { return new ReadOnlyCollection<string>(names); } } 
    } 
    [Identifiers(new string[] {"Bill", "Ben", "Ted"})] 
    static class SomeClass 
    { 
     public static void TellMeAboutYourself() 
     { 
      Identifiers theAttribute = (Identifiers)Attribute.GetCustomAttribute(typeof(SomeClass), typeof(Identifiers)); 
      foreach (var s in theAttribute.Names) 
      { 
       Console.WriteLine(s); 
      } 
     } 
    } 
} 
2

你也可以使用 「PARAMS字符串[]別名」 在構造函數中,使變量參數列表:

[AttributeUsage(AttributeTargets.Method)] 
class TestAttribute : Attribute 
{ 
    public TestAttribute(params string[] aliases) 
    { 
     allowedAliases = aliases; 
    } 

    public string[] allowedAliases { get; set; } 

} 

這將允許你這樣做:

[Test("test1", "test2", "test3")] 
static void Main(string[] args) 
+0

+1比我的漂亮! – 2009-10-21 22:47:04