首先,我知道这个问题: Best Practices and How to support different versions of REST APIs in C# wrapper on client-side 但我认为我的问题有点不同。
我们有一个可以通过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 :(得分:4)
<强>更新强> 调整“每种方法都需要不同的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 :(得分: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");
}