ISB001 Dispose of proxies
Proxies obtained from IServiceBroker.GetProxyAsync<T> must always be disposed of.
Until they are explicitly disposed of, I/O resources are allocated to them that will not be released naturally by the garbage collector.
Although the interface T returned from this method does not clearly implement IDisposable, the proxy instance returned does in fact implement IDisposable.
Examples of patterns that are flagged by this analyzer
The following code acquires and uses a proxy to a brokered service but does not dispose of it. This generates a diagnostic.
IMyService client = await serviceBroker.GetProxyAsync<IMyService>(someDescriptor);
if (client is object)
{
await client.FooAsync();
}
In another example, the proxy is stored in a member (field or property) instead of a local variable.
This is wrong both because this.client must be disposed of in a Dispose method and because this.client should be disposed of before being reassigned:
class MyClass
{
IMyService client;
async Task DoSomethingAsync()
{
this.client = await serviceBroker.GetProxyAsync<IMyService>(someDescriptor);
if (this.client is object)
{
await this.client.FooAsync();
}
}
}
Solution
Fix the error by ensuring that the proxy gets disposed of.
When the proxy is stored in a local variable, use a using block:
using (IMyService client = await serviceBroker.GetProxyAsync<IMyService>(someDescriptor))
{
if (client is object)
{
await client.FooAsync();
}
}
If IMyService does not derive from IDisposable, use this syntax:
IMyService client = await serviceBroker.GetProxyAsync<IMyService>(someDescriptor);
using (client as IDisposable)
{
if (client is object)
{
await client.FooAsync();
}
}
When the proxy is stored in a member, dispose of it before any reassignment, and in the Dispose method:
class MyClass : IDisposable
{
IMyService client;
async Task DoSomethingAsync()
{
(this.client as IDisposable)?.Dispose();
this.client = await serviceBroker.GetProxyAsync<IMyService>(someDescriptor);
if (this.client is object)
{
await this.client.FooAsync();
}
}
public void Dispose()
{
(this.client as IDisposable)?.Dispose();
}
}