有一个具有3个接口的应用程序,任何想使用此应用程序的人都需要实现这些接口。我创建了一个类库项目,该项目具有这些接口实现,我已从同一基类继承了所有接口实现,以便能够拥有一个HttpClient。到目前为止,这是我所做的:
public class BaseProxy
{
protected static readonly HttpClient Client;
static BaseProxy()
{
Client = new HttpClient();
}
}
并且我在所有派生类中都使用了此Client来进行GetAsync和PostAsync请求,如下所示:
public class XProxyImplementation
{
var response = Client.GetAsync(BaseUrl + "XXXApi/GetClientSettings/").Result;
response.EnsureSuccessStatusCode();
}
顺便说一句,Web API中的所有方法都不是异步的,因此我选择了单例解决方案,因为我不想为每个请求使用using块。我的问题是我应该使用DI解决方案,还是此代码足够用于内部使用的应用程序?欢迎提出所有改进建议。
我已经阅读了许多有关使用DI容器的答案,但这只是具有代理实现的类库。
我的另一个担心是,即使我想使用DI,目前也无法在构造函数类中引入DI,因为使用我的实现的另一个应用程序正在寻找空的构造函数。当我尝试将HttpClient参数传递给构造函数时,出现以下错误:
当前类型System.Net.Http.HttpMessageHandler是一个抽象 类,无法构建
使用我的dll的应用程序不允许我将任何参数传递给使用任何抽象类的构造函数。我猜这个应用程序使用Unity进行握手,并以某种方式寻找空的构造函数。尝试进行以下更改后,我得到了错误:
public BaseProxy() : this(Service.HttpClient)
{
}
public XProxyImplementation(HttpClient client) : base(client)
{
}
这就是为什么我实际上更喜欢单例实例而不是DI实现。
答案 0 :(得分:0)
我肯定会使用Microsoft.Extensions.DependencyInjection包来提供DI解决方案。 https://dzone.com/articles/dependency-injection-in-net-core-console-applicati
您还应该非常了解如何使用异步方法(如GetAsync)。 使用.Result几乎永远不会给出期望的结果,您最好使方法异步并使用await关键字,如下所示:
var response = await Client.GetAsync(BaseUrl + "XXXApi/GetClientSettings/");
https://montemagno.com/c-sharp-developers-stop-calling-dot-result/
是了解此最佳做法的方式和方式的好资源
答案 1 :(得分:0)
DI是答案。如果您不想使用ID,则可以实现一个HttpClientFactory。 你可以在这里阅读更多 https://docs.microsoft.com/en-us/dotnet/architecture/microservices/implement-resilient-applications/use-httpclientfactory-to-implement-resilient-http-requests
答案 2 :(得分:0)
DI将启用代理类的可测试性,而当前的实现不能进行单元测试。它还将改善关注点分离:remove the responsibility控制HttpClient
的生存期与代理之间。
通常,您会执行以下操作:
public abstract class BaseProxy
{
protected readonly HttpClient Client;
protected BaseProxy(HttpClient client)
{
Client = client;
}
// ... other members
}
public class XProxyImplementation : BaseProxy
{
public XProxyImplementation(HttpClient client) : base(client)
{
}
// ... other members
public Task SendRequest() // for example
{
return Client.GetAsync("....");
}
}
在测试期间,您将初始化HttpClient
的另一个实例,并注入HttpMessageHandler
的易于测试的实现:
// you implement TestHttpMessageHandler that aids your tests
var httpClient = new HttpClient(new TestHttpMessageHandler());
var proxyUnderTest = new XProxyImplementation(httpClient);
有关使用HttpClient
和HttpMessageHandler
进行单元测试的说明,请参见this blog post。
现在我们在您的代码中引入了依赖注入,下一个问题是,应该使用哪种注入机制。
在您的特定情况下,我不赞成耦合到任何特定的DI容器,因为您希望您的库被许多不同的应用程序使用,并且您不想膨胀它们的依赖关系(一个应用程序可能已经在使用不同的DI容器)。
此外,由于您发布的代码非常简单,因此,成熟的DI容器可能会显得过分杀伤力。在生产代码中,您只需将单身HttpClient
移至“服务定位器”:
public static class SingletonServices
{
public static readonly HttpClient HttpClient;
static SingletonServices()
{
HttpClient = new HttpClient();
}
}
因此,当您在生产代码中实例化代理时,请执行以下操作:
var proxy = new XProxyImplementation(SingletonServices.HttpClient);