5.17继承复用与冻结参数

HTTP 声明式请求支持面向对象的封装与继承等特性。可将通用接口定义在父接口中,再由派生接口继承,实现复用。例如:

继承与复用#

HTTP 声明式请求支持面向对象的封装与继承等特性。可将通用接口定义在父接口中,再由派生接口继承,实现复用。例如:

cs
public interface IHttpBaseService : IHttpDeclarative{    [Get("https://furion.net/")]    Task<string> GetStringAsync();}public interface IHttp1 : IHttpBaseService{    [Get("https://baiqian.com/")]    Task<string> GetWebsiteAsync();}

此外,也支持继承未实现 IHttpDeclarative 接口的普通接口,例如:

cs
public interface IHttpNormal{    [Get("https://baiqian.com/")]    Task<string> GetBaiduAsync();}public interface IHttp2 : IHttpNormal, IHttpBaseService{    // ...}

借助封装与继承,可以更高效地组织与复用代码。

冻结参数类型#

在之前的章节中,我们多次提及冻结参数类型,现在终于可以对其进行深入探讨了。

在系统中,Action<HttpRequestMessage>Action<HttpRequestBuilder>Action<HttpMultipartFormDataBuilder>HttpCompletionOption 以及 CancellationToken 被定义为冻结参数类型,它们专门服务于 HTTP 声明式请求接口,以提供额外的配置和操作功能。这些冻结参数类型能够极大地扩展 HTTP 声明式请求接口的功能,使其覆盖更广泛的使用场景。

  • Action<HttpRequestMessage>

此参数允许开发者在调用 HTTP 声明式接口时,对 HttpClient 发送的 HttpRequestMessage 进行额外的配置。例如,添加自定义的 HTTP 头、设置认证信息等。相应的 HTTP 声明式提取器实现为 HttpRequestMessageDeclarativeExtractor 类型,该类型负责解析单个 Action<HttpRequestMessage> 类型参数,并提供发送请求前的操作。

cs
public interface IHttpService : IHttpDeclarative{    [Post("https://furion.net/")]    Task<string> PostStringAsync([QueryParam] int id, [Body("application/json")] object body, Action<HttpRequestMessage>? configure = null)}
cs
// 默认调用await httpService.PostStringAsync(1, new { id = 1, name = "Furion" });// 提供更多 HttpRequestMessage 配置await httpService.PostStringAsync(1, new { id = 1, name = "Furion" }, requestMessage =>{    requestMessage.Headers.TryAddWithoutValidation("header1", "value1");    // 例如添加名为 "header1" 的请求标头});
  • Action<HttpRequestBuilder>

此参数允许开发者在调用 HTTP 声明式接口时,对 HttpRequestBuilder 进行额外的配置。例如,添加自定义的 HTTP 头、设置认证信息等。相应的 HTTP 声明式提取器实现为 HttpRequestBuilderDeclarativeExtractor 类型,该类型负责解析单个 Action<HttpRequestBuilder> 类型参数,并提供构建 HttpRequestBuilder 实例额外的配置。

cs
public interface IHttpService : IHttpDeclarative{    [Post("https://furion.net/")]    Task<string> PostStringAsync([QueryParam] int id, [Body("application/json")] object body, Action<HttpRequestBuilder>? configure = null)}
cs
// 默认调用await httpService.PostStringAsync(1, new { id = 1, name = "Furion" });// 提供更多 HttpRequestBuilder 配置await httpService.PostStringAsync(1, new { id = 1, name = "Furion" }, builder =>{    builder.AddBearerAuthentication("your-token");   // 例如添加 Bearer 授权});
  • Action<HttpMultipartFormDataBuilder>

此参数用于配置多部分表单数据的设置。通过它,开发者可以添加文件、设置文件类型等。相应的 HTTP 声明式提取器实现为 HttpMultipartFormDataBuilderDeclarativeExtractor 类型,该类型负责解析单个 Action<HttpMultipartFormDataBuilder> 类型参数,并提供构建 HttpMultipartFormDataBuilder 多部分表单实例额外的配置。

cs
public interface IHttpService : IHttpDeclarative{    [Post("https://furion.net/")]    Task<string> PostStringAsync([Multipart] string name, Action<HttpMultipartFormDataBuilder>? configure = null);}
cs
// 默认调用await httpService.PostStringAsync("Furion");// 提供更多配置多部分表单内容配置await httpService.PostStringAsync("Furion", multipart =>{    multipart.AddFileAsStream(@"C:\Workspaces\httptest.jpg", "files", contentType: "image/jpeg");    multipart.AddFileFromBase64String("77u/5rWL6K+V5paH5Lu25YaF5a65", "files");    multipart.AddFileFromRemote("https://furion.net/img/furionlogo.png", "files");});
  • HttpCompletionOption

此参数用于指定 HTTP 响应的读取方式。例如,是否等待整个响应内容读取完毕再返回,还是只读取响应头即返回。

cs
public interface IHttpService : IHttpDeclarative{    [Get("https://furion.net/")]    Task<Stream> GetStreamAsync([QueryParam] string version, HttpCompletionOption completionOption = HttpCompletionOption.ResponseContentRead);}
cs
// 默认调用await httpService.GetStreamAsync("v4");// 自定义响应读取方式await httpService.GetStreamAsync("v5", HttpCompletionOption.ResponseHeadersRead);
  • CancellationToken

此参数允许开发者在发送 HTTP 请求时,提供可取消操作的配置。通过它,可以设定请求在特定条件下被取消。

cs
public interface IHttpService : IHttpDeclarative{    [Get("https://furion.net/")]    Task<Stream> GetStreamAsync(CancellationToken cancellationToken = default);}
cs
// 默认调用(无法取消)await httpService.GetStreamAsync("v4");// 设置 100 毫秒后取消请求using var cancellationTokenSource = new CancellationTokenSource();cancellationTokenSource.CancelAfter(100);await httpService.GetStreamAsync("v5", cancellationTokenSource.Token);  // 假设该请求时间大于 100 毫秒

值得注意的是,这些冻结参数类型可以组合使用,并且通常(建议)放在方法参数列表的最后面,作为可选配置。但同一方法参数定义中,同类型的冻结参数必须是唯一的,否则将抛出 InvalidOperationException 异常。

cs
public interface IHttpService : IHttpDeclarative{    // 支持组合使用    [Post("https://furion.net/")]    Task<string> PostStringAsync([QueryParam] int id, [Body("application/json")] object body,        Action<HttpMultipartFormDataBuilder>? multipartConfigure = null,        Action<HttpRequestBuilder>? configure = null,        HttpCompletionOption completionOption = HttpCompletionOption.ResponseContentRead,        CancellationToken cancellationToken = default);    // Action<HttpRequestBuilder> 类型参数不是唯一的,将抛出异常 ❎    [Post("https://furion.net/")]    Task<string> PostStringAsync([QueryParam] int id, [Body("application/json")] object body,        Action<HttpRequestBuilder>? configure = null,        Action<HttpRequestBuilder>? configure1 = null);}

通过这些冻结参数类型,HTTP 声明式请求接口不仅极大地减轻了开发人员编写 HTTP 请求代码的负担,而且使得代码结构更加清晰、易于维护和复用。