之前的文章我已經(jīng)大概介紹了httpclient的使用方法晴叨。那么作為想進(jìn)步(zhuang bi)仰泻、追求真理(you jie cao)的一個(gè)碼農(nóng)瓶埋,我們更想知道這個(gè)東東內(nèi)部到底是怎么實(shí)現(xiàn)的呢捞挥?于是就有了該系列文章浮创。
說(shuō)明:由于源碼分析本來(lái)就是枯燥乏味,有時(shí)候會(huì)很難懂砌函。所以
作者將它按照系列分開(kāi)來(lái)寫斩披。作者水平有限,寫作過(guò)程中可能會(huì)錯(cuò)誤或者不足讹俊,還請(qǐng)大家及時(shí)評(píng)論或者建議垦沉。我會(huì)針對(duì)您的反饋積極做出修改。在這里提前謝謝大家H耘2薇丁!
目錄
HttpClient
話不多說(shuō)先來(lái)一段源碼贩疙。HttpClient位于System.Net.Http.dll
命名空間中讹弯。
using System;
using System.Globalization;
using System.IO;
using System.Net.Http.Headers;
using System.Runtime.CompilerServices;
using System.Threading;
using System.Threading.Tasks;
namespace System.Net.Http
{
[__DynamicallyInvokable]
public class HttpClient : HttpMessageInvoker
{
[CompilerGenerated]
[Serializable]
private sealed class <>c
{
public static readonly HttpClient.<>c <>9 = new HttpClient.<>c();
public static Func<HttpContent, Task<string>> <>9__26_0;
public static Func<HttpContent, Task<byte[]>> <>9__28_0;
public static Func<HttpContent, Task<Stream>> <>9__30_0;
internal Task<string> <GetStringAsync>b__26_0(HttpContent content)
{
return content.ReadAsStringAsync();
}
internal Task<byte[]> <GetByteArrayAsync>b__28_0(HttpContent content)
{
return content.ReadAsByteArrayAsync();
}
internal Task<Stream> <GetStreamAsync>b__30_0(HttpContent content)
{
return content.ReadAsStreamAsync();
}
}
private static readonly TimeSpan defaultTimeout = TimeSpan.FromSeconds(100.0);
private static readonly TimeSpan maxTimeout = TimeSpan.FromMilliseconds(2147483647.0);
private static readonly TimeSpan infiniteTimeout = TimeSpan.FromMilliseconds(-1.0);
private const HttpCompletionOption defaultCompletionOption = HttpCompletionOption.ResponseContentRead;
private volatile bool operationStarted;
private volatile bool disposed;
private CancellationTokenSource pendingRequestsCts;
private HttpRequestHeaders defaultRequestHeaders;
private Uri baseAddress;
private TimeSpan timeout;
private long maxResponseContentBufferSize;
[__DynamicallyInvokable]
public HttpRequestHeaders DefaultRequestHeaders
{
[__DynamicallyInvokable]
get
{
if (this.defaultRequestHeaders == null)
{
this.defaultRequestHeaders = new HttpRequestHeaders();
}
return this.defaultRequestHeaders;
}
}
[__DynamicallyInvokable]
public Uri BaseAddress
{
[__DynamicallyInvokable]
get
{
return this.baseAddress;
}
[__DynamicallyInvokable]
set
{
HttpClient.CheckBaseAddress(value, "value");
this.CheckDisposedOrStarted();
if (Logging.On)
{
Logging.PrintInfo(Logging.Http, this, "BaseAddress: '" + this.baseAddress + "'");
}
this.baseAddress = value;
}
}
[__DynamicallyInvokable]
public TimeSpan Timeout
{
[__DynamicallyInvokable]
get
{
return this.timeout;
}
[__DynamicallyInvokable]
set
{
if (value != HttpClient.infiniteTimeout && (value <= TimeSpan.Zero || value > HttpClient.maxTimeout))
{
throw new ArgumentOutOfRangeException("value");
}
this.CheckDisposedOrStarted();
this.timeout = value;
}
}
[__DynamicallyInvokable]
public long MaxResponseContentBufferSize
{
[__DynamicallyInvokable]
get
{
return this.maxResponseContentBufferSize;
}
[__DynamicallyInvokable]
set
{
if (value <= 0L)
{
throw new ArgumentOutOfRangeException("value");
}
if (value > 2147483647L)
{
throw new ArgumentOutOfRangeException("value", value, string.Format(CultureInfo.InvariantCulture, SR.net_http_content_buffersize_limit, new object[]
{
2147483647L
}));
}
this.CheckDisposedOrStarted();
this.maxResponseContentBufferSize = value;
}
}
[__DynamicallyInvokable]
public HttpClient() : this(new HttpClientHandler())
{
}
[__DynamicallyInvokable]
public HttpClient(HttpMessageHandler handler) : this(handler, true)
{
}
[__DynamicallyInvokable]
public HttpClient(HttpMessageHandler handler, bool disposeHandler) : base(handler, disposeHandler)
{
if (Logging.On)
{
Logging.Enter(Logging.Http, this, ".ctor", handler);
}
this.timeout = HttpClient.defaultTimeout;
this.maxResponseContentBufferSize = 2147483647L;
this.pendingRequestsCts = new CancellationTokenSource();
if (Logging.On)
{
Logging.Exit(Logging.Http, this, ".ctor", null);
}
}
[__DynamicallyInvokable]
public Task<string> GetStringAsync(string requestUri)
{
return this.GetStringAsync(this.CreateUri(requestUri));
}
[__DynamicallyInvokable]
public Task<string> GetStringAsync(Uri requestUri)
{
HttpCompletionOption arg_27_2 = HttpCompletionOption.ResponseContentRead;
string arg_27_3 = string.Empty;
Func<HttpContent, Task<string>> arg_27_4;
if ((arg_27_4 = HttpClient.<>c.<>9__26_0) == null)
{
arg_27_4 = (HttpClient.<>c.<>9__26_0 = new Func<HttpContent, Task<string>>(HttpClient.<>c.<>9.<GetStringAsync>b__26_0));
}
return this.GetContentAsync<string>(requestUri, arg_27_2, arg_27_3, arg_27_4);
}
[__DynamicallyInvokable]
public Task<byte[]> GetByteArrayAsync(string requestUri)
{
return this.GetByteArrayAsync(this.CreateUri(requestUri));
}
[__DynamicallyInvokable]
public Task<byte[]> GetByteArrayAsync(Uri requestUri)
{
HttpCompletionOption arg_27_2 = HttpCompletionOption.ResponseContentRead;
byte[] arg_27_3 = HttpUtilities.EmptyByteArray;
Func<HttpContent, Task<byte[]>> arg_27_4;
if ((arg_27_4 = HttpClient.<>c.<>9__28_0) == null)
{
arg_27_4 = (HttpClient.<>c.<>9__28_0 = new Func<HttpContent, Task<byte[]>>(HttpClient.<>c.<>9.<GetByteArrayAsync>b__28_0));
}
return this.GetContentAsync<byte[]>(requestUri, arg_27_2, arg_27_3, arg_27_4);
}
[__DynamicallyInvokable]
public Task<Stream> GetStreamAsync(string requestUri)
{
return this.GetStreamAsync(this.CreateUri(requestUri));
}
[__DynamicallyInvokable]
public Task<Stream> GetStreamAsync(Uri requestUri)
{
HttpCompletionOption arg_27_2 = HttpCompletionOption.ResponseHeadersRead;
Stream arg_27_3 = Stream.Null;
Func<HttpContent, Task<Stream>> arg_27_4;
if ((arg_27_4 = HttpClient.<>c.<>9__30_0) == null)
{
arg_27_4 = (HttpClient.<>c.<>9__30_0 = new Func<HttpContent, Task<Stream>>(HttpClient.<>c.<>9.<GetStreamAsync>b__30_0));
}
return this.GetContentAsync<Stream>(requestUri, arg_27_2, arg_27_3, arg_27_4);
}
private Task<T> GetContentAsync<T>(Uri requestUri, HttpCompletionOption completionOption, T defaultValue, Func<HttpContent, Task<T>> readAs)
{
TaskCompletionSource<T> tcs = new TaskCompletionSource<T>();
Action<Task<T>> <>9__1;
this.GetAsync(requestUri, completionOption).ContinueWithStandard(delegate(Task<HttpResponseMessage> requestTask)
{
if (HttpClient.HandleRequestFaultsAndCancelation<T>(requestTask, tcs))
{
return;
}
HttpResponseMessage result = requestTask.Result;
if (result.Content == null)
{
tcs.TrySetResult(defaultValue);
return;
}
try
{
Task<T> arg_62_0 = readAs(result.Content);
Action<Task<T>> arg_62_1;
if ((arg_62_1 = <>9__1) == null)
{
arg_62_1 = (<>9__1 = delegate(Task<T> contentTask)
{
if (!HttpUtilities.HandleFaultsAndCancelation<T>(contentTask, tcs))
{
tcs.TrySetResult(contentTask.Result);
}
});
}
arg_62_0.ContinueWithStandard(arg_62_1);
}
catch (Exception exception)
{
tcs.TrySetException(exception);
}
});
return tcs.Task;
}
[__DynamicallyInvokable]
public Task<HttpResponseMessage> GetAsync(string requestUri)
{
return this.GetAsync(this.CreateUri(requestUri));
}
[__DynamicallyInvokable]
public Task<HttpResponseMessage> GetAsync(Uri requestUri)
{
return this.GetAsync(requestUri, HttpCompletionOption.ResponseContentRead);
}
[__DynamicallyInvokable]
public Task<HttpResponseMessage> GetAsync(string requestUri, HttpCompletionOption completionOption)
{
return this.GetAsync(this.CreateUri(requestUri), completionOption);
}
[__DynamicallyInvokable]
public Task<HttpResponseMessage> GetAsync(Uri requestUri, HttpCompletionOption completionOption)
{
return this.GetAsync(requestUri, completionOption, CancellationToken.None);
}
[__DynamicallyInvokable]
public Task<HttpResponseMessage> GetAsync(string requestUri, CancellationToken cancellationToken)
{
return this.GetAsync(this.CreateUri(requestUri), cancellationToken);
}
[__DynamicallyInvokable]
public Task<HttpResponseMessage> GetAsync(Uri requestUri, CancellationToken cancellationToken)
{
return this.GetAsync(requestUri, HttpCompletionOption.ResponseContentRead, cancellationToken);
}
[__DynamicallyInvokable]
public Task<HttpResponseMessage> GetAsync(string requestUri, HttpCompletionOption completionOption, CancellationToken cancellationToken)
{
return this.GetAsync(this.CreateUri(requestUri), completionOption, cancellationToken);
}
[__DynamicallyInvokable]
public Task<HttpResponseMessage> GetAsync(Uri requestUri, HttpCompletionOption completionOption, CancellationToken cancellationToken)
{
return this.SendAsync(new HttpRequestMessage(HttpMethod.Get, requestUri), completionOption, cancellationToken);
}
[__DynamicallyInvokable]
public Task<HttpResponseMessage> PostAsync(string requestUri, HttpContent content)
{
return this.PostAsync(this.CreateUri(requestUri), content);
}
[__DynamicallyInvokable]
public Task<HttpResponseMessage> PostAsync(Uri requestUri, HttpContent content)
{
return this.PostAsync(requestUri, content, CancellationToken.None);
}
[__DynamicallyInvokable]
public Task<HttpResponseMessage> PostAsync(string requestUri, HttpContent content, CancellationToken cancellationToken)
{
return this.PostAsync(this.CreateUri(requestUri), content, cancellationToken);
}
[__DynamicallyInvokable]
public Task<HttpResponseMessage> PostAsync(Uri requestUri, HttpContent content, CancellationToken cancellationToken)
{
return this.SendAsync(new HttpRequestMessage(HttpMethod.Post, requestUri)
{
Content = content
}, cancellationToken);
}
[__DynamicallyInvokable]
public Task<HttpResponseMessage> PutAsync(string requestUri, HttpContent content)
{
return this.PutAsync(this.CreateUri(requestUri), content);
}
[__DynamicallyInvokable]
public Task<HttpResponseMessage> PutAsync(Uri requestUri, HttpContent content)
{
return this.PutAsync(requestUri, content, CancellationToken.None);
}
[__DynamicallyInvokable]
public Task<HttpResponseMessage> PutAsync(string requestUri, HttpContent content, CancellationToken cancellationToken)
{
return this.PutAsync(this.CreateUri(requestUri), content, cancellationToken);
}
[__DynamicallyInvokable]
public Task<HttpResponseMessage> PutAsync(Uri requestUri, HttpContent content, CancellationToken cancellationToken)
{
return this.SendAsync(new HttpRequestMessage(HttpMethod.Put, requestUri)
{
Content = content
}, cancellationToken);
}
[__DynamicallyInvokable]
public Task<HttpResponseMessage> DeleteAsync(string requestUri)
{
return this.DeleteAsync(this.CreateUri(requestUri));
}
[__DynamicallyInvokable]
public Task<HttpResponseMessage> DeleteAsync(Uri requestUri)
{
return this.DeleteAsync(requestUri, CancellationToken.None);
}
[__DynamicallyInvokable]
public Task<HttpResponseMessage> DeleteAsync(string requestUri, CancellationToken cancellationToken)
{
return this.DeleteAsync(this.CreateUri(requestUri), cancellationToken);
}
[__DynamicallyInvokable]
public Task<HttpResponseMessage> DeleteAsync(Uri requestUri, CancellationToken cancellationToken)
{
return this.SendAsync(new HttpRequestMessage(HttpMethod.Delete, requestUri), cancellationToken);
}
[__DynamicallyInvokable]
public Task<HttpResponseMessage> SendAsync(HttpRequestMessage request)
{
return this.SendAsync(request, HttpCompletionOption.ResponseContentRead, CancellationToken.None);
}
[__DynamicallyInvokable]
public override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
return this.SendAsync(request, HttpCompletionOption.ResponseContentRead, cancellationToken);
}
[__DynamicallyInvokable]
public Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, HttpCompletionOption completionOption)
{
return this.SendAsync(request, completionOption, CancellationToken.None);
}
[__DynamicallyInvokable]
public Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, HttpCompletionOption completionOption, CancellationToken cancellationToken)
{
if (request == null)
{
throw new ArgumentNullException("request");
}
this.CheckDisposed();
HttpClient.CheckRequestMessage(request);
this.SetOperationStarted();
this.PrepareRequestMessage(request);
CancellationTokenSource linkedCts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, this.pendingRequestsCts.Token);
this.SetTimeout(linkedCts);
TaskCompletionSource<HttpResponseMessage> tcs = new TaskCompletionSource<HttpResponseMessage>();
base.SendAsync(request, linkedCts.Token).ContinueWithStandard(delegate(Task<HttpResponseMessage> task)
{
try
{
this.DisposeRequestContent(request);
if (task.IsFaulted)
{
this.SetTaskFaulted(request, linkedCts, tcs, task.Exception.GetBaseException());
}
else if (task.IsCanceled)
{
this.SetTaskCanceled(request, linkedCts, tcs);
}
else
{
HttpResponseMessage result = task.Result;
if (result == null)
{
this.SetTaskFaulted(request, linkedCts, tcs, new InvalidOperationException(SR.net_http_handler_noresponse));
}
else if (result.Content == null || completionOption == HttpCompletionOption.ResponseHeadersRead)
{
this.SetTaskCompleted(request, linkedCts, tcs, result);
}
else
{
this.StartContentBuffering(request, linkedCts, tcs, result);
}
}
}
catch (Exception ex)
{
if (Logging.On)
{
Logging.Exception(Logging.Http, this, "SendAsync", ex);
}
tcs.TrySetException(ex);
}
});
return tcs.Task;
}
[__DynamicallyInvokable]
public void CancelPendingRequests()
{
this.CheckDisposed();
if (Logging.On)
{
Logging.Enter(Logging.Http, this, "CancelPendingRequests", "");
}
CancellationTokenSource cancellationTokenSource = Interlocked.Exchange<CancellationTokenSource>(ref this.pendingRequestsCts, new CancellationTokenSource());
cancellationTokenSource.Cancel();
cancellationTokenSource.Dispose();
if (Logging.On)
{
Logging.Exit(Logging.Http, this, "CancelPendingRequests", "");
}
}
[__DynamicallyInvokable]
protected override void Dispose(bool disposing)
{
if (disposing && !this.disposed)
{
this.disposed = true;
this.pendingRequestsCts.Cancel();
this.pendingRequestsCts.Dispose();
}
base.Dispose(disposing);
}
private void DisposeRequestContent(HttpRequestMessage request)
{
HttpContent content = request.Content;
if (content != null)
{
content.Dispose();
}
}
private void StartContentBuffering(HttpRequestMessage request, CancellationTokenSource cancellationTokenSource, TaskCompletionSource<HttpResponseMessage> tcs, HttpResponseMessage response)
{
response.Content.LoadIntoBufferAsync(this.maxResponseContentBufferSize).ContinueWithStandard(delegate(Task contentTask)
{
try
{
bool isCancellationRequested = cancellationTokenSource.Token.IsCancellationRequested;
if (contentTask.IsFaulted)
{
response.Dispose();
if (isCancellationRequested && contentTask.Exception.GetBaseException() is HttpRequestException)
{
this.SetTaskCanceled(request, cancellationTokenSource, tcs);
}
else
{
this.SetTaskFaulted(request, cancellationTokenSource, tcs, contentTask.Exception.GetBaseException());
}
}
else if (contentTask.IsCanceled)
{
response.Dispose();
this.SetTaskCanceled(request, cancellationTokenSource, tcs);
}
else
{
this.SetTaskCompleted(request, cancellationTokenSource, tcs, response);
}
}
catch (Exception ex)
{
response.Dispose();
tcs.TrySetException(ex);
if (Logging.On)
{
Logging.Exception(Logging.Http, this, "SendAsync", ex);
}
}
});
}
private void SetOperationStarted()
{
if (!this.operationStarted)
{
this.operationStarted = true;
}
}
private void CheckDisposedOrStarted()
{
this.CheckDisposed();
if (this.operationStarted)
{
throw new InvalidOperationException(SR.net_http_operation_started);
}
}
private void CheckDisposed()
{
if (this.disposed)
{
throw new ObjectDisposedException(base.GetType().FullName);
}
}
private static void CheckRequestMessage(HttpRequestMessage request)
{
if (!request.MarkAsSent())
{
throw new InvalidOperationException(SR.net_http_client_request_already_sent);
}
}
private void PrepareRequestMessage(HttpRequestMessage request)
{
Uri uri = null;
if (request.RequestUri == null && this.baseAddress == null)
{
throw new InvalidOperationException(SR.net_http_client_invalid_requesturi);
}
if (request.RequestUri == null)
{
uri = this.baseAddress;
}
else if (!request.RequestUri.IsAbsoluteUri)
{
if (this.baseAddress == null)
{
throw new InvalidOperationException(SR.net_http_client_invalid_requesturi);
}
uri = new Uri(this.baseAddress, request.RequestUri);
}
if (uri != null)
{
request.RequestUri = uri;
}
if (this.defaultRequestHeaders != null)
{
request.Headers.AddHeaders(this.defaultRequestHeaders);
}
}
private static void CheckBaseAddress(Uri baseAddress, string parameterName)
{
if (baseAddress == null)
{
return;
}
if (!baseAddress.IsAbsoluteUri)
{
throw new ArgumentException(SR.net_http_client_absolute_baseaddress_required, parameterName);
}
if (!HttpUtilities.IsHttpUri(baseAddress))
{
throw new ArgumentException(SR.net_http_client_http_baseaddress_required, parameterName);
}
}
private void SetTaskFaulted(HttpRequestMessage request, CancellationTokenSource cancellationTokenSource, TaskCompletionSource<HttpResponseMessage> tcs, Exception e)
{
this.LogSendError(request, cancellationTokenSource, "SendAsync", e);
tcs.TrySetException(e);
cancellationTokenSource.Dispose();
}
private void SetTaskCanceled(HttpRequestMessage request, CancellationTokenSource cancellationTokenSource, TaskCompletionSource<HttpResponseMessage> tcs)
{
this.LogSendError(request, cancellationTokenSource, "SendAsync", null);
tcs.TrySetCanceled();
cancellationTokenSource.Dispose();
}
private void SetTaskCompleted(HttpRequestMessage request, CancellationTokenSource cancellationTokenSource, TaskCompletionSource<HttpResponseMessage> tcs, HttpResponseMessage response)
{
if (Logging.On)
{
Logging.PrintInfo(Logging.Http, this, string.Format(CultureInfo.InvariantCulture, SR.net_http_client_send_completed, new object[]
{
Logging.GetObjectLogHash(request),
Logging.GetObjectLogHash(response),
response
}));
}
tcs.TrySetResult(response);
cancellationTokenSource.Dispose();
}
private void SetTimeout(CancellationTokenSource cancellationTokenSource)
{
if (this.timeout != HttpClient.infiniteTimeout)
{
cancellationTokenSource.CancelAfter(this.timeout);
}
}
private void LogSendError(HttpRequestMessage request, CancellationTokenSource cancellationTokenSource, string method, Exception e)
{
if (cancellationTokenSource.IsCancellationRequested)
{
if (Logging.On)
{
Logging.PrintError(Logging.Http, this, method, string.Format(CultureInfo.InvariantCulture, SR.net_http_client_send_canceled, new object[]
{
Logging.GetObjectLogHash(request)
}));
return;
}
}
else if (Logging.On)
{
Logging.PrintError(Logging.Http, this, method, string.Format(CultureInfo.InvariantCulture, SR.net_http_client_send_error, new object[]
{
Logging.GetObjectLogHash(request),
e
}));
}
}
private Uri CreateUri(string uri)
{
if (string.IsNullOrEmpty(uri))
{
return null;
}
return new Uri(uri, UriKind.RelativeOrAbsolute);
}
private static bool HandleRequestFaultsAndCancelation<T>(Task<HttpResponseMessage> task, TaskCompletionSource<T> tcs)
{
if (HttpUtilities.HandleFaultsAndCancelation<T>(task, tcs))
{
return true;
}
HttpResponseMessage result = task.Result;
if (!result.IsSuccessStatusCode)
{
if (result.Content != null)
{
result.Content.Dispose();
}
tcs.TrySetException(new HttpRequestException(string.Format(CultureInfo.InvariantCulture, SR.net_http_message_not_success_statuscode, new object[]
{
(int)result.StatusCode,
result.ReasonPhrase
})));
return true;
}
return false;
}
}
}
眼尖的同學(xué)估計(jì)看出來(lái)了,這不是真正的源碼罢饨ΑU⒂ぁ!芍躏!當(dāng)然這個(gè)代碼反編譯工具是給搞出來(lái)的源碼這哦。這里重點(diǎn)推薦下ILSpy工具降狠。建議大家都來(lái)安裝下对竣。
看分??析
-
HttpClient
繼承自HttpMessageInvoker
-
HttpMessageInvoker
具有一個(gè)SendAsync
方法庇楞,其實(shí)就是這個(gè)方法用戶向目標(biāo)服務(wù)器發(fā)送HttpRequsetMessage
對(duì)象承載的HTTP請(qǐng)求接,并通過(guò)HttpResponseMessage
對(duì)象來(lái)接收服務(wù)器返回?cái)?shù)據(jù)否纬。吕晌。(關(guān)于這點(diǎn)我們來(lái)看截圖,有圖有真相A偃肌)
- 注意看
HttpClient
這個(gè)的空參構(gòu)造函數(shù)睛驳,后面會(huì)講到哦。
HttpMessageInvoker
“擼”一段源碼
using System;
using System.Threading;
using System.Threading.Tasks;
namespace System.Net.Http
{
[__DynamicallyInvokable]
public class HttpMessageInvoker : IDisposable
{
private volatile bool disposed;
private bool disposeHandler;
private HttpMessageHandler handler;
[__DynamicallyInvokable]
public HttpMessageInvoker(HttpMessageHandler handler) : this(handler, true)
{
}
[__DynamicallyInvokable]
public HttpMessageInvoker(HttpMessageHandler handler, bool disposeHandler)
{
if (Logging.On)
{
Logging.Enter(Logging.Http, this, ".ctor", handler);
}
if (handler == null)
{
throw new ArgumentNullException("handler");
}
if (Logging.On)
{
Logging.Associate(Logging.Http, this, handler);
}
this.handler = handler;
this.disposeHandler = disposeHandler;
if (Logging.On)
{
Logging.Exit(Logging.Http, this, ".ctor", null);
}
}
[__DynamicallyInvokable]
public virtual Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
if (request == null)
{
throw new ArgumentNullException("request");
}
this.CheckDisposed();
if (Logging.On)
{
Logging.Enter(Logging.Http, this, "SendAsync", Logging.GetObjectLogHash(request) + ": " + request);
}
Task<HttpResponseMessage> task = this.handler.SendAsync(request, cancellationToken);
if (Logging.On)
{
Logging.Exit(Logging.Http, this, "SendAsync", task);
}
return task;
}
[__DynamicallyInvokable]
public void Dispose()
{
this.Dispose(true);
GC.SuppressFinalize(this);
}
[__DynamicallyInvokable]
protected virtual void Dispose(bool disposing)
{
if (disposing && !this.disposed)
{
this.disposed = true;
if (this.disposeHandler)
{
this.handler.Dispose();
}
}
}
private void CheckDisposed()
{
if (this.disposed)
{
throw new ObjectDisposedException(base.GetType().FullName);
}
}
}
}
看分??析
- 從構(gòu)造函數(shù)中不難看出膜廊,
HttpMessageInvoker
是對(duì)一個(gè)HttpMessageHandler
對(duì)象封裝乏沸。實(shí)際在SendAsync
方法中,“發(fā)送請(qǐng)求爪瓜、接收響應(yīng)”的任務(wù)最終都是通過(guò)調(diào)用HttpMessageHandler
中的同名SendAsync
方法來(lái)實(shí)現(xiàn)蹬跃。(關(guān)于這點(diǎn)我們來(lái)看截圖,有圖有真相C)
看了這個(gè)圖是不是已經(jīng)明白了,這里的
this
就是構(gòu)造函數(shù)中初始化的HttpMessageHandler
對(duì)象啊蝶缀。
HttpMessageInvoker利用HttpMessageHandler完成請(qǐng)求發(fā)送和響應(yīng)接收原理圖
-
HttpMessageInvoker
類型實(shí)現(xiàn)了IDisposable
接口,它通過(guò)實(shí)現(xiàn)的Dispose
方法來(lái)釋放被封裝的HttpMessageHandler
對(duì)象薄货。但是當(dāng)一個(gè)HttpMessageInvoker
被釋放的時(shí)候翁都,并不一定要求釋放被其封裝的HttpMessageHandler
對(duì)象,是否需要對(duì)其實(shí)施釋放操作取決于構(gòu)建HTTP MessageInvoker
時(shí)傳入的disposeHandler
參數(shù)谅猾。
參考文獻(xiàn)
- 《ASP.NET WebAPI 2 框架揭秘》
- MSDN
- 博客園