Skip to content

Commit 4c3661e

Browse files
author
David Francis
committed
Made DelegateFluentClient and FluentClient implement IDisposable.
1 parent 5db4622 commit 4c3661e

File tree

6 files changed

+129
-8
lines changed

6 files changed

+129
-8
lines changed

Client/Default/FluentClient.cs

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,8 @@ public FluentClient(HttpClient client, TMessageHandler handler, string baseUri =
4848
/// <returns>Returns a request builder.</returns>
4949
public IRequest DeleteAsync(string resource)
5050
{
51+
this.AssertNotDisposed();
52+
5153
return this.SendAsync(HttpMethod.Delete, resource);
5254
}
5355

@@ -56,6 +58,8 @@ public IRequest DeleteAsync(string resource)
5658
/// <returns>Returns a request builder.</returns>
5759
public IRequest GetAsync(string resource)
5860
{
61+
this.AssertNotDisposed();
62+
5963
return this.SendAsync(HttpMethod.Get, resource);
6064
}
6165

@@ -64,6 +68,8 @@ public IRequest GetAsync(string resource)
6468
/// <returns>Returns a request builder.</returns>
6569
public IRequest PostAsync(string resource)
6670
{
71+
this.AssertNotDisposed();
72+
6773
return this.SendAsync(HttpMethod.Post, resource);
6874
}
6975

@@ -74,6 +80,8 @@ public IRequest PostAsync(string resource)
7480
/// <returns>Returns a request builder.</returns>
7581
public IRequest PostAsync<TBody>(string resource, TBody body)
7682
{
83+
this.AssertNotDisposed();
84+
7785
return this.PostAsync(resource).WithBody(body);
7886
}
7987

@@ -82,6 +90,8 @@ public IRequest PostAsync<TBody>(string resource, TBody body)
8290
/// <returns>Returns a request builder.</returns>
8391
public IRequest PutAsync(string resource)
8492
{
93+
this.AssertNotDisposed();
94+
8595
return this.SendAsync(HttpMethod.Put, resource);
8696
}
8797

@@ -92,6 +102,8 @@ public IRequest PutAsync(string resource)
92102
/// <returns>Returns a request builder.</returns>
93103
public IRequest PutAsync<TBody>(string resource, TBody body)
94104
{
105+
this.AssertNotDisposed();
106+
95107
return this.PutAsync(resource).WithBody(body);
96108
}
97109

@@ -101,6 +113,8 @@ public IRequest PutAsync<TBody>(string resource, TBody body)
101113
/// <returns>Returns a request builder.</returns>
102114
public virtual IRequest SendAsync(HttpMethod method, string resource)
103115
{
116+
this.AssertNotDisposed();
117+
104118
Uri uri = new Uri(this.BaseClient.BaseAddress, resource);
105119
HttpRequestMessage message = this.Factory.GetRequestMessage(method, uri, this.Formatters);
106120
return this.SendAsync(message);
@@ -111,6 +125,8 @@ public virtual IRequest SendAsync(HttpMethod method, string resource)
111125
/// <returns>Returns a request builder.</returns>
112126
public virtual IRequest SendAsync(HttpRequestMessage message)
113127
{
128+
this.AssertNotDisposed();
129+
114130
return this.Factory.GetRequest(message, this.Formatters, request => this.BaseClient.SendAsync(request.Message));
115131
}
116132

@@ -131,13 +147,58 @@ protected FluentClient()
131147
/// <param name="factory">Constructs implementations for the fluent client.</param>
132148
protected void Initialize(HttpClient client, TMessageHandler handler, string baseUri = null, IFactory factory = null)
133149
{
150+
this.AssertNotDisposed();
151+
134152
this.MessageHandler = handler;
135153
this.BaseClient = client;
136154
this.Factory = factory ?? new Factory();
137155
if (baseUri != null)
138156
this.BaseClient.BaseAddress = new Uri(baseUri);
139157
this.Formatters = this.Factory.GetDefaultFormatters();
140158
}
159+
160+
161+
/*********
162+
** Dispose methods
163+
*********/
164+
/// <summary>Whether the client has been disposed.</summary>
165+
private bool _disposed = false;
166+
167+
// Public implementation of Dispose pattern callable by consumers.
168+
void IDisposable.Dispose()
169+
{
170+
this.Dispose(true);
171+
GC.SuppressFinalize(this);
172+
}
173+
174+
/// <summary>Protected implementation of Dispose pattern.</summary>
175+
/// <param name="isDisposing">Set if the dispose method was explicitly called.</param>
176+
protected virtual void Dispose(bool isDisposing)
177+
{
178+
if (_disposed)
179+
return;
180+
181+
if (isDisposing)
182+
{
183+
this.MessageHandler.Dispose();
184+
this.BaseClient.Dispose();
185+
}
186+
187+
_disposed = true;
188+
}
189+
190+
/// <summary>Destruct the instance.</summary>
191+
~FluentClient()
192+
{
193+
Dispose(false);
194+
}
195+
196+
/// <summary>Assert that the instance is not disposed.</summary>
197+
private void AssertNotDisposed()
198+
{
199+
if (_disposed)
200+
throw new ObjectDisposedException(nameof(FluentClient<TMessageHandler>));
201+
}
141202
}
142203

143204
/// <summary>Sends HTTP requests and receives responses from a resource identified by a URI.</summary>

Client/Delegating/DelegatingFluentClient.cs

Lines changed: 60 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
using System.Net.Http;
1+
using System;
2+
using System.Net.Http;
23
using System.Net.Http.Formatting;
34

45
namespace Pathoschild.Http.Client.Delegating
@@ -45,6 +46,8 @@ public virtual MediaTypeFormatterCollection Formatters
4546
/// <returns>Returns a request builder.</returns>
4647
public virtual IRequest DeleteAsync(string resource)
4748
{
49+
this.AssertNotDisposed();
50+
4851
return this.Implementation.DeleteAsync(resource);
4952
}
5053

@@ -53,6 +56,8 @@ public virtual IRequest DeleteAsync(string resource)
5356
/// <returns>Returns a request builder.</returns>
5457
public virtual IRequest GetAsync(string resource)
5558
{
59+
this.AssertNotDisposed();
60+
5661
return this.Implementation.GetAsync(resource);
5762
}
5863

@@ -61,6 +66,8 @@ public virtual IRequest GetAsync(string resource)
6166
/// <returns>Returns a request builder.</returns>
6267
public virtual IRequest PostAsync(string resource)
6368
{
69+
this.AssertNotDisposed();
70+
6471
return this.Implementation.PostAsync(resource);
6572
}
6673

@@ -71,6 +78,8 @@ public virtual IRequest PostAsync(string resource)
7178
/// <returns>Returns a request builder.</returns>
7279
public virtual IRequest PostAsync<TBody>(string resource, TBody body)
7380
{
81+
this.AssertNotDisposed();
82+
7483
return this.Implementation.PostAsync<TBody>(resource, body);
7584
}
7685

@@ -79,6 +88,8 @@ public virtual IRequest PostAsync<TBody>(string resource, TBody body)
7988
/// <returns>Returns a request builder.</returns>
8089
public virtual IRequest PutAsync(string resource)
8190
{
91+
this.AssertNotDisposed();
92+
8293
return this.Implementation.PutAsync(resource);
8394
}
8495

@@ -89,6 +100,8 @@ public virtual IRequest PutAsync(string resource)
89100
/// <returns>Returns a request builder.</returns>
90101
public virtual IRequest PutAsync<TBody>(string resource, TBody body)
91102
{
103+
this.AssertNotDisposed();
104+
92105
return this.Implementation.PutAsync<TBody>(resource, body);
93106
}
94107

@@ -98,6 +111,8 @@ public virtual IRequest PutAsync<TBody>(string resource, TBody body)
98111
/// <returns>Returns a request builder.</returns>
99112
public virtual IRequest SendAsync(HttpMethod method, string resource)
100113
{
114+
this.AssertNotDisposed();
115+
101116
return this.Implementation.SendAsync(method, resource);
102117
}
103118

@@ -107,6 +122,8 @@ public virtual IRequest SendAsync(HttpMethod method, string resource)
107122
/// <remarks>This is the base method which executes every request.</remarks>
108123
public virtual IRequest SendAsync(HttpRequestMessage message)
109124
{
125+
this.AssertNotDisposed();
126+
110127
return this.Implementation.SendAsync(message);
111128
}
112129

@@ -120,6 +137,48 @@ protected DelegatingFluentClient(IClient<TMessageHandler> client)
120137
{
121138
this.Implementation = client;
122139
}
140+
141+
142+
/*********
143+
** Dispose methods
144+
*********/
145+
/// <summary>Whether the client has been disposed.</summary>
146+
private bool _disposed = false;
147+
148+
// Public implementation of Dispose pattern callable by consumers.
149+
void IDisposable.Dispose()
150+
{
151+
this.Dispose(true);
152+
GC.SuppressFinalize(this);
153+
}
154+
155+
/// <summary>Protected implementation of Dispose pattern.</summary>
156+
/// <param name="isDisposing">Set if the dispose method was explicitly called.</param>
157+
protected virtual void Dispose(bool isDisposing)
158+
{
159+
if (_disposed)
160+
return;
161+
162+
if (isDisposing)
163+
{
164+
this.Implementation.Dispose();
165+
}
166+
167+
_disposed = true;
168+
}
169+
170+
/// <summary>Destruct the instance.</summary>
171+
~DelegatingFluentClient()
172+
{
173+
Dispose(false);
174+
}
175+
176+
/// <summary>Assert that the instance is not disposed.</summary>
177+
private void AssertNotDisposed()
178+
{
179+
if (_disposed)
180+
throw new ObjectDisposedException(nameof(DelegatingFluentClient<TMessageHandler>));
181+
}
123182
}
124183

125184
/// <summary>Sends HTTP requests and receives responses from a resource identified by a URI.</summary>

Client/IClient.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
1-
using System.Net.Http;
1+
using System;
2+
using System.Net.Http;
23
using System.Net.Http.Formatting;
34

45
namespace Pathoschild.Http.Client
56
{
67
/// <summary>Sends HTTP requests and receives responses from REST URIs.</summary>
78
/// <typeparam name="TMessageHandler">The HTTP message handler type.</typeparam>
8-
public interface IClient<out TMessageHandler>
9+
public interface IClient<out TMessageHandler> : IDisposable
910
where TMessageHandler : HttpMessageHandler
1011
{
1112
/*********

Client/package.nuspec

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
<package>
33
<metadata>
44
<id>Pathoschild.Http.FluentClient</id>
5-
<version>1.2.0</version>
5+
<version>1.2.1</version>
66
<authors>Jesse Plamondon-Willard</authors>
77
<description>A fluent, strongly-typed HTTP client built on top of Microsoft's .NET 4.5 HttpClient.</description>
88
<licenseUrl>https://creativecommons.org/licenses/by/3.0/</licenseUrl>
@@ -13,6 +13,6 @@
1313
<dependencies>
1414
<dependency id="Microsoft.AspNet.WebApi.Client" version="5.0" />
1515
</dependencies>
16-
<releaseNotes>Migrated to latest Microsoft packages.</releaseNotes>
16+
<releaseNotes>Made DelegateFluentClient and FluentClient implement IDisposable.</releaseNotes>
1717
</metadata>
1818
</package>

GlobalAssemblyInfo.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,5 @@
99
[assembly: AssemblyTrademark("")]
1010
[assembly: AssemblyCulture("")]
1111
[assembly: ComVisible(false)]
12-
[assembly: AssemblyVersion("1.2.0.0")]
13-
[assembly: AssemblyFileVersion("1.2.0.0")]
12+
[assembly: AssemblyVersion("1.2.1.0")]
13+
[assembly: AssemblyFileVersion("1.2.1.0")]

Tests/Integration/IntegrationTests.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ protected void AssertResponse(WikipediaMetadata response, string prefix)
108108
.AssertValue(p => p.Base, "http://en.wikipedia.org/wiki/Main_Page")
109109
.AssertValue(p => p.Language, "en")
110110
.AssertValue(p => p.MainPage, "Main Page")
111-
.AssertValue(p => p.MaxUploadSize, 1048576000)
111+
.AssertValue(p => p.MaxUploadSize, 1048576000)
112112
.AssertValue(p => p.ScriptPath, "/w")
113113
.AssertValue(p => p.Server, "//en.wikipedia.org")
114114
.AssertValue(p => p.SiteName, "Wikipedia")

0 commit comments

Comments
 (0)