我正在为新的Web API创建一个C#包装器库。
该服务提供了一组API,其中每个方法接收几个必需参数,以及一些可选参数(每个方法可能接收不同的强制/可选参数)。
参数以POST方式发送,作为长串的param = value& param2 = value2& ....
习惯了基于界面的设计 - 在这种情况下是否适合?
我找不到一个很好的解决方案,可以将所有API方法和参数映射到单个界面中,而不会产生方法重载,造成大麻烦,这会让用户更难以使用。
它的外观示例:
public interface IServiceAPI
{
void MethodA(string mandatory, string mandatory2);
void MethodA(string mandatory, string mandatory2, int optional);
void MethodB(string mandatory);
... etc
}
基于接口的设计是否适合这里?或换句话说 - 基于界面的设计最适合哪里?
答案 0 :(得分:2)
首先,我不认为设计具有大量重载的接口是个好主意。除非函数执行某些不同的,否则如果他们想要输入一些默认值,则应该将其留给使用该界面的人。
那就是说,其次你正在写的实体似乎会更好地为你提供基类。 ServiceAPI这个名称有助于暗示至少一些标准功能。通过这种方式,您可以拥有多个重载,并让任何子类覆盖主方法。
答案 1 :(得分:1)
接口是正确的方法,但我认为你使用的是错误的接口。我将创建一个IOptionalParameter接口,如下所示:
interface IOptionalParameter<T>
{
public bool IsSet {get;}
public T Value {get;}
}
然后,您可以在API中公开一个方法,每个参数的类型为IOptionalParameter。
这也将使您用于构建url请求字符串的代码更整洁。如果它有意义,你可以在界面中添加一个Name属性,从而进一步简化它。
<强>更新强>
总结三种不同的方法以及它们之间的权衡:
答案 2 :(得分: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。当我看到您提供的示例时,我会关注单一责任原则。当然,如果不知道我只是猜测的实际代码,那么请将其视为一条建议。
答案 3 :(得分: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.
答案 4 :(得分: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();
如果他们不想为可选参数设置值,他们可以跳过它。