0

我有一個包裝Mercurial命令行客戶端的類庫。如何創建一個可擴展的API,並仍然使用對象初始值設定語法?

我的意圖是實現對所有內置命令的支持,但除此之外,還有很多擴展。

所以我需要讓我的庫可擴展,因爲其他人和我都可以添加對擴展的支持。我計劃增加對一些比較流行和典型的擴展的支持(至少是與Mercurial捆綁在一起的很多擴展),但我仍然希望能夠從外部擴展它。

目前,命令語法如下所示:

Repo.Execute(new CommitCommand 
{ 
    Message = "Your commit message", 
    AddRemove = true, 
}); 

然而,這並不很容易借本身的擴展,而程序員感覺這個擴展只是上漲了部分。

舉例來說,假設我揭露的額外的命令行參數的公共收藏,我可以手動執行此操作:

var cmd = new CommitCommand 
{ 
    Message = "Your commit message", 
    AddRemove = true, 
}; 
cmd.Arguments.Add("--my-commit-extension"); 
Repo.Execute(cmd); 

似乎有是沒有簡單的方法,我得到額外的擴展添加以這種方式可以將其設置爲對象初始值設定項的一部分。

我一直在考慮添加,或者可能切換到流暢的接口語法。在這種情況下,你可以寫這樣的事情:

Repo.Execute(new CommitCommand() 
    .Message("Your commit message") 
    .AddRemove() 
    .MyCommitExtension()); 

但是,我看到人們不喜歡通順接口,他們覺得他們變得過於健談。

我還有其他選擇嗎?

我想要什麼,基本上是:

  • 一個常見的語法風格
    • 對於這兩個內置的我的媒體庫的用戶添加的東西
    • 除了擴展

我想我的圖書館的用戶可以通過添加新的類和擴展方法來擴展它t intellisense支持,但擴展方法不能用於對象初始化器,這意味着所有的擴展看起來像是一些事後的想法。這不是我想要的。

歡迎任何想法。

回答

1

我對Mercurial並不熟悉,你的問題似乎過於籠統,無法專門解決,但我可以解決一個特別的問題。

var cmd = new CommitCommand 
{ 
    Message = "Your commit message", 
    AddRemove = true, 
}; 
cmd.Arguments.Add("--my-commit-extension"); 
Repo.Execute(cmd); 

如果CommitCommand。參數是IList<T>你已經使用初始化語法的能力:

class CommitCommand 
{ 
    public string Message { get; set; } 
    public bool AddRemove { get; set; } 
    public List<string> Arguments = new List<string>(); 
} 

Repo.Execute(new CommitCommand 
{ 
    Message = "Your commit message", 
    AddRemove = true, 
    Arguments = { "--my-commit-extension", "--my-other-commit-extension" } 
}); 
+0

是的,但不好意思,我的失誤,我簡化。我打算使用常規方法,以便使用庫+擴展的程序員不必知道實際參數。 – 2010-12-05 18:21:48

1

我也是不那麼熟悉的Mercurial,而是一種選擇是智能感知出來扔掉,並使用匿名類型:

Repo.Execute(new 
{ 
    Message = "Your commit message", 
    AddRemove = true, 
    MyCommitExtension = null 
}); 

你不能在屬性名稱中使用連字符,因此您需要從PascalCase替換爲連字符小寫。或者,你可以用超時替換下劃線。

我不知道我會推薦這種方法不知道人們將使用這些擴展的頻率。在處理HTML屬性時,這種方法在ASP.NET MVC框架中效果很好,但是這種情況不同,因爲框架不需要處理值,它只是直接將它們寫入輸出。如果您正在根據以這種方式提供的值採取條件操作,或者您希望您的API對於不知道Mercurial命令行語法的用戶更容易發現,那麼您可以嘗試其他方法。

0

至於我流利的界面是好的。但是,如果你不想使用它,那麼我可能會使用水木清華這樣的:

interface IExtension { ... } 

class SomeExtension1 : IExtension { ... } 
class SomeExtension2 : IExtension { ... } 

class CommitCommand 
{ 
    public string Message; 
    public bool AddRemove; 
    public readonly IList<IExtension> Extensions = new List<IExtension>(); 
} 

這將允許以這種方式使用命令:

new CommitCommand 
{ 
    Message = "", 
    AddRemove = true, 
    Extensions = {new SomeExtension1(), new SomeExtension2()} 
}; 
相關問題