注意:标题是一个问题,但实际上我有3个问题要问。
我正在使用Autofac DI容器来解决依赖关系。
如果对此代码还有其他改进,请提出建议。
我已经浏览了以下链接:
Implementing IDisposable correctly
Implementing a Dispose method
IDisposable Part 1
请考虑以下代码:
界面:IHttpClient
public interface IHttpClient : IDisposable
{
HttpRequestHeaders DefaultRequestHeaders { get; set; } // Question 1
Uri BaseAddress { get; set; }
Task<HttpResponseMessage> PostAsync(string uri, HttpContent httpContent);
}
类:HttpClientAdaptor
internal HttpClientAdaptor : IHttpClient
{
private HttpRequestHeaders _defaultRequestHeaders;
private bool _disposed = false;
public HttpRequestHeaders DefaultRequestHeaders
{
get
{
if (_defaultRequestHeaders == null)
_defaultRequestHeaders = new HttpClient().DefaultRequestHeaders;
return _defaultRequestHeaders;
}
set
{
if (value != null)
_defaultRequestHeaders = value;
}
}
public Uri BaseAddress { get; set; }
private async Task<HttpResponseMessage> PostAsync(Uri uri, HttpContent httpContent, CancellationToken cancellationToken)
{
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, uri)
{
Content = httpContent
};
return await new HttpMessageInvoker(new HttpClientHandler()).SendAsync(request, cancellationToken); // Question 2
}
protected virtual void Dispose(bool disposing)
{
if (!_disposed)
{
if (disposing)
{
_defaultRequestHeaders = null;
BaseAddress = new Uri(); // Question 3
}
_disposed = true;
}
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
}
考虑以下类,接口IHttpClient
和// Question 1
:
class DS
{
private IHttpClient _apiClient;
public class DS(/*other dependencies*/, IHttpClient apiClient)
{
_apiClient = apiClient;
}
// At somepoint I need to perform the following operation
private void SomeMethod(string hostname, /*other params*/)
{
_apiClient.BaseAddress = new Uri(hostName);
_apiClient.DefaultRequestHeaders.Accept.Clear(); // this line throws exception as "DefaultRequestHeaders" is null
_apiClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
}
}
问题1 :当我已经解决依赖项时,为什么会引发null异常。为了避免这种情况,我必须添加以下行:
_apiClient.DefaultRequestHeaders = new HttpClientAdaptor().DefaultRequestHeaders;
是否有更好的方法,而不是在需要DefaultRequestHeader
的任何地方都使用上面提到的代码?
问题2 :考虑class HttpClientAdaptor
并评论// Question 2
。我需要拨打SendAsync()
。这是正确的方法还是我应该继承class HttpMessageInvoker
。还是有第三种方法?
问题3 :考虑class HttpClientAdaptor
并评论// Question 3
。这是处置托管代码的正确方法吗?如果是,那我应该如何处置财产BaseAddress
?如果没有,请提出正确的建议。当然,由于明显的原因,当前代码会给出编译时错误。
答案 0 :(得分:1)
问题1: 如注释中所述,没有DI会通过调用get属性来初始化字段,因此您需要做的是在构造函数中移动初始化。
问题2:正如要在单元测试中使用注释中指出的那样,您尚不清楚要实现什么目标。一个人不要在模拟中进行实际的调用。因此,也许您还需要其他东西?例如。要记住调用发生了,并且调用时可能使用了参数。
问题3:
不,这似乎不是处理您实现它的方式的正确方法。在以下两种情况下,需要实施IDisposable
:
IDisposable
成员,您需要在此呼叫Dispose
您似乎并没有遇到任何这样的情况,因此您根本不需要在内部处理任何事情,因为由于您正在重新实现系统,因此看来您根本就没有它。界面。
这仍然意味着,尽管那些将使用您的HttpClientAdaptor
类的人将需要进行处分,因为他们不知道它实际上没有任何作用。当然,如果您自己使用它,也可以跳过调用处置,而不会产生任何后果。
P.S。如果将您的类用于单元测试,则可以使用为此目的而设计的模拟库之一,它将动态地完成这项工作。 Moq
或NSubstitute
是很好的候选人。