2016-02-12 85 views
0

首先,我知道這個問題: Best Practices and How to support different versions of REST APIs in C# wrapper on client-side 但我認爲我的問題有點不同。支持REST方法檢查的最佳做法

我們有一塊軟件可以通過REST API進行遠程控制。 用戶每年會得到一次更新〜兩次。 每次更新都會爲他們提供一些新功能。

現在我們還有一個REST客戶端,它是並行開發的,但具有不同的發佈日期。除了新版本之外,客戶端還必須支持舊版本。

現在的問題是,我想知道如何在我的REST客戶端代碼中構建版本檢查。這是一個有點奢侈設計問題...

public void apiStuff(Data input) 
{ 
    if (api.Versions < "2.5.3") 
     throw new Exception("Not supported, please update") 

    doApiStuffWith(input); 
} 

,或者我應該把檢查,並扔在一個私有方法一部分。

public void apiStuff(Data input) 
{ 
    checkForVersionSupport("2.5.3"); 

    doApiStuffWith(input); 
} 

我認爲第一種方法是作爲第二個更可讀的,但是它也是冗餘代碼。

還是有人有完全不同的想法?

+0

所以你檢查你的服務器的API版本的使用情況如何?這對我來說沒有意義。此外,您所做的選擇實際上並沒有太大的差別,顯然將功能提取到另一個功能更好。雖然我會使用某種鉤子而不是在每個api調用中調用它。 – Glubus

+0

MS使用V2。您也可以嘗試代碼合同。這就是說,你的問題是基於意見的。 –

回答

4

UPDATE 調整爲「每種方法都需要不同的api版本」解決方案。

摘要客戶端邏輯接口:

public interface IApiClient 
{ 
    void Foo(); 
    int GetCurrentVersion(); 
} 

做一個屬性的方法,通過法API版本:

[AttributeUsage(AttributeTargets.Method, AllowMultiple = false)] 
public sealed class ApiVersionRangeAttribute : Attribute 
{ 
    public int MinVersion { get; private set; } 
    public int MaxVersion { get; private set; } 
    public ApiVersionRangeAttribute(int minVersion, int maxVersion) 
    { 
     MinVersion = minVersion; 
     MaxVersion = maxVersion; 
    } 

    public void Validate(int version) 
    { 
     if (version < MinVersion || version > MaxVersion) 
     { 
      throw new Exception("Upgrade"); 
     } 
    } 
} 

,並創建一個工廠,將採取該屬性到一筆賬:

//nuget: Install-Package Castle.Core 
using System; 
using Castle.DynamicProxy; 
public class ApiClientFactory 
{ 
    public class ApiClient : IApiClient 
    { 
     [ApiVersionRange(10, 20)] 
     public void Foo() 
     { 
      Console.Write("Foo"); 
     } 
     public int GetCurrentVersion() 
     { 
      // call to the server here instead :) 
      return 50; 
     } 
    } 

    public IApiClient CreateClient() 
    { 
     var generator = new ProxyGenerator(); 
     var apiClient = generator.CreateInterfaceProxyWithTarget<IApiClient>(
      new ApiClient(), new VersionInterceptor()); 
     return apiClient; 
    } 
} 

public class VersionInterceptor : StandardInterceptor 
{ 
    protected override void PreProceed(IInvocation invocation) 
    { 
     var attributes = invocation.MethodInvocationTarget.GetCustomAttributes(
      typeof(ApiVersionRangeAttribute), false); 
     if (attributes != null && attributes.Length == 1) 
     { 
      var apiRange = (ApiVersionRangeAttribute)attributes[0]; 
      var proxy = (IApiClient)invocation.Proxy; 
      apiRange.Validate(proxy.GetCurrentVersion()); 
     } 
     base.PreProceed(invocation); 
    } 
} 

使用範例:

var apiClient = new ApiClientFactory().CreateClient(); 
// fail - 50 is not in range 10-20 
apiClient.Foo(); 
+1

所以我應該爲每一個版本構建一個新的客戶端,並在實例化時檢查版本? 這對我的情況來說是很大的開銷。有很多不同的版本。 – Alu

+0

此解決方案將避免使用舊客戶端版本和新服務器版本的可能性。這不符合要求。 –

+0

是的,當然,但我想用戶得到一個消息,他必須更新。 因此,如果他「看到」他不能使用的功能,他就會被迫更新他的服務器。 – Alu

1

恕我直言考慮Version代替int和使用AttributeUsage以備不時之需。

以上回答已經描繪屬性

public void CheckVersion(Version currentVersion) 
{ 
    //Get your version from assembly 
    Version applicationVersion = new Version(AssemblyInfo.AssemblyFileVersion); 

    // 
    if (currentVersion.CompareTo(applicationVersion) == 1) 
     throw your Exception("Not supported"); 
}