2012-05-09 81 views
1

我正在爲新的Web API創建C#包裝庫。基於接口的設計和可選的方法參數

該服務提供了一組幾個API,其中每個方法接收多個必需參數,以及幾個可選參數(每個方法可能會接收不同的強制/可選參數)。

的參數在POST方法發送的,作爲PARAM的一個長字符串=值& param2的=值2 & ....

已經習慣於接口基於設計 - 它是一個良好的配合在該案件?

我無法找到一個很好的解決方案,將所有的API方法和參數映射到一個接口中,而不會創建一個方法重載,創建一個大混亂,這會讓用戶更難使用。

什麼它可能看起來像

例子:

public interface IServiceAPI 
{ 
    void MethodA(string mandatory, string mandatory2); 
    void MethodA(string mandatory, string mandatory2, int optional); 
    void MethodB(string mandatory); 

    ... etc 
} 
  • 我知道在.NET 4中引入的可選參數這不是一個很好的解決方案,因爲這個庫是針對較低版本.NET,還因爲「可選參數」實際上只是一種設置默認值的方法,而不是爲參數不發送任何值。

是基於接口的設計在這裏很適合嗎?或者換句話說 - 界面設計最適合的地方在哪裏?

+0

爲什麼不使用可選參數void MethodA(string mandatory,string mandatory2 = String.Empty,int optional = 0); – Habib

+0

查看我更新的問題。 –

+0

基於界面的設計究竟是什麼意思?你的意思是編程接口而不是實現?如果你不使用'基於接口的設計',你會怎麼做? –

回答

1

看來您的方法傾向於具有多個參數。根據我的經驗,最多應該有3個論點。爲了解決這個問題(和副作用找到可選/所需參數的解決方案)我建議包裝參數爲一類:

class MethodAParameters 
{ 
    public string Required1 {get;set;} //add validation in setter (nulls are not allowed) 
    public string Required2 {get;set;} //add validation in setter (nulls are not allowed) 
    public int? Optional1 {get;set;} //nulls allowed 

    public MethodAParameters(string required1, string required2) 
    { 
     Required1 = required1; 
     Required2 = required2; 
    } 
} 

正如你所看到的,這樣的設計強制執行傳遞所需的參數(你不能創建一個參數實例而不指定它們),並允許添加可選參數。 當然,如果某些方法共享相同的參數子集,那麼您應該繼承參數類。

如果空值也是相關的,那麼之前提到的IOptionalParameter似乎是必要的(與此參數類方法結合)。

請注意,您的代碼應該是SOLID。當我看看你提供的例子時,我很關心單一責任原則。當然,如果不知道實際的代碼,我只能猜測,所以請把它當作一條忠告。

+0

這種方法的缺點是我必須使用屬性PER方法來定義一個類。 –

+1

取決於你的API的樣子。繼承在這裏可能會有所幫助。但是來吧,課程很便宜:)作爲回報,你有一個明確定義的API,這很容易理解。 – dzendras

+0

這種設計實際上是我認爲對這種情況最好的設計(比專業人士更有利)。實際上,我曾與一個具有相似設計的SDK一起工作,以解決相似的情況。 –

2

首先,我不認爲設計一個有很多重載接口是一個好主意。除非函數做了一些不同的,如果他們想要放入一些默認值,你應該讓它保持使用接口的人。

也就是說,其次,您正在編寫的實體看起來好像能爲您提供更好的基礎類。 ServiceAPI這個名稱有助於暗示至少有一些標準功能。這樣你可以有多個重載,並讓任何子類覆蓋主要方法。

0

可爲空的數據類型?

例如,而不是

void MethodA(string mandatory, string mandatory2); 
void MethodA(string mandatory, string mandatory2, int optional); 

您可以簡化這

void MethodA(string mandatory, string mandatory2, int? optional); 

但是,如果可選參數是引用類型,那麼它可能不是那麼明顯給調用者,他們能夠只是將null傳遞給它。

如果你有很多可選參數,與V同樣oid MethodC(string mandatory, string mandatory2, string optional1, int? optional1, string optional2);你不想爲所有可能的組合提供的簽名,你可以簡單地提供:

MethodC(string mandatory, string mandatory2) // for people that just want the basic functionality 
MethodC(string mandatory, string mandatory2, string optional1, int? optional1, string optional2); // for people that want to specify extra, and they can pass null for some of the optional ones if they like. 
1

接口是正確的路要走,但我認爲你使用的是錯誤的。我會按如下方式創建一個IOptionalParameter接口:

interface IOptionalParameter<T> 
{ 
    public bool IsSet {get;} 
    public T Value {get;} 
} 

然後你就可以有型IOptionalParameter的每個參數做你的API中暴露的只是一個方法。

這也將使您用於構建url請求字符串neater的代碼。如果有意義的話,你也可以在界面上添加一個Name屬性,從而進一步簡化它。

更新

總結三種不同的方法和權衡兩者之間:

  1. 重載 - 這是更清楚的是參數是可選的,但會導致混亂,實施電位差並使實現有點混亂
  2. 可以爲空的類型 - 不是非常明確的參數是可選的,但在實現方面更乾淨
  3. IOptionalParameter - 明確指出參數是可選的或不可執行,並且實現是乾淨的但可以從客戶端調用
+0

如何表示調用方法的參數不應該被使用呢? –

+0

@liortal IsSet = false – Slugart

+0

這使得調用方法非常麻煩 –

0

我不知道爲什麼你想要作爲一個接口,而不是普通的類。其他類是否會實現這個接口,還是隻是尋找一種訪問API的標準方式?

如果您只是尋找一種訪問API的標準方式,我會建議構建器模式的變體。構建器模式通常用於類,但我不明白爲什麼它不能用於方法。有關幾個基於類的示例,請參見http://cdmckay.org/blog/2009/07/03/joshua-blochs-builder-pattern-in-csharp/

這是我給你提供的東西的嘗試。我很抱歉,如果有語法錯誤,我在家裏編輯有點欠缺......

public class AccessServiceAPI 
{ 
    private void MethodA(string mandatory, string mandatory2, string optional) 
    { 
     // do stuff 
    } 

    public class MethodABuilder 
    { 
     private string Mandatory { get; set; } 
     private string Mandatory2 { get; set; } 
     private string Optional { get; set; } 

     public MethodABuilder(string mandatory, string mandatory2) 
     { 
      Mandatory = mandatory; 
      Mandatory2 = mandatory; 
      Optional = "default value"; 
     } 

     public MethodABuilder Optional(string optional) 
     { 
      Optional = optional; 
      return this; 
     } 

     public void Build() 
     { 
      MethodA(mandatory, mandatory2, optional); 
     } 
    } 
} 

的客戶端將然後調用該方法是這樣的:

MethodABuilder.Builder(mandatory, mandatory2).Optional(optional).Build(); 

如果他們不希望設置一個可選參數的值,他們可以跳過它。