gpt4 book ai didi

c# - 从 MVP Winform 客户端使用 WebAPI 的设计模式

转载 作者:太空狗 更新时间:2023-10-29 23:05:56 26 4
gpt4 key购买 nike

背景

我正在构建一个两层应用程序:

  • 第 1 层:使用 MVP(模型- View -呈现器)设计模式的 Winforms 应用程序。
  • 第 2 层:WebAPI RESTful 服务。

Winforms 客户端将使用 HttpClient 使用 WebAPI 服务。这两层都大量使用 IoC 和依赖注入(inject)设计模式

问题

当 Winforms 应用程序需要来自 WebAPI 服务的数据时,演示者将协调请求。我的问题是,您会直接在 Presenter 内部使用 HttpClient 吗?为了保持演示者可测试,您如何确保不必依赖具体的 HttpClient 调用?我正在考虑以某种方式整合来自这个 question 的最佳答案.

最佳答案

我通过抽象一切来解决这个问题。

在表示层我会有一个服务抽象...

public interface IServiceAgent {
Task<SomeResultObject> GetSomething(string myParameter);
}

...从 Web API 中抽象出我想要的内容。演示者不需要协调请求。演示者不关心数据来自何处。它只知道它想要某样东西并提出要求 (SoC)。这是服务代理的工作 (SRP)。

服务代理实现可能需要调用不同的数据源。包括网络。因此,抽象化 HttpClient 将放松与该实现的耦合。

一个简单的例子,比如...

public interface IHttpClient {
System.Threading.Tasks.Task<T> GetAsync<T>(string uri) where T : class;
System.Threading.Tasks.Task<T> GetAsync<T>(Uri uri) where T : class;
//...other members as needed : DeleteAsync, PostAsync, PutAsync...etc
}

一些示例实现看起来像这样......

public class MyPresenter {
public MyPresenter(IServiceAgent services) {...}
}

public class MyDefaultServiceAgent : IServiceAgent {
IHttpClient httpClient;

public MyDefaultServiceAgent (IHttpClient httpClient) {
this.httpClient = httpClient;
}

public async Task<SomeResultObject> GetSomething(string myParameter) {
var url = "http://localhost/my_web_api_endpoint?q=" + myParameter;
var result = await httpClient.GetAsync<SomeResultObject>(url);
return result;
}
}

public class MyDefaultHttpClient : IHttpClient {
HttpClient httpClient; //The real thing

public MyDefaultHttpClient() {
httpClient = createHttpClient();
}

/// <summary>
/// Send a GET request to the specified Uri as an asynchronous operation.
/// </summary>
/// <typeparam name="T">Response type</typeparam>
/// <param name="uri">The Uri the request is sent to</param>
/// <returns></returns>
public System.Threading.Tasks.Task<T> GetAsync<T>(string uri) where T : class {
return GetAsync<T>(new Uri(uri));
}

/// <summary>
/// Send a GET request to the specified Uri as an asynchronous operation.
/// </summary>
/// <typeparam name="T">Response type</typeparam>
/// <param name="uri">The Uri the request is sent to</param>
/// <returns></returns>
public async System.Threading.Tasks.Task<T> GetAsync<T>(Uri uri) where T : class {
var result = default(T);
//Try to get content as T
try {
//send request and get the response
var response = await httpClient.GetAsync(uri).ConfigureAwait(false);
//if there is content in response to deserialize
if (response.Content.Headers.ContentLength.GetValueOrDefault() > 0) {
//get the content
string responseBodyAsText = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
//desrialize it
result = deserializeJsonToObject<T>(responseBodyAsText);
}
} catch (Exception ex) {
Log.Error(ex);
}
return result;
}

private static T deserializeJsonToObject<T>(string json) {
var result = JsonSerializer.Deserialize<T>(json);
return result;
}
}

通过抽象这些依赖关系,您可以通过允许使用伪造/模拟服务代理进行单元测试来保持演示者的可测试性。您可以使用伪造/模拟的 HTTP 客户端测试您的服务代理。如果您需要更改/交换/维护您的应用程序组件,它还允许您注入(inject)这些接口(interface)的任何具体实现。

关于c# - 从 MVP Winform 客户端使用 WebAPI 的设计模式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37765869/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com