Skip to main content

DisposableHelpers by Clynt Neiko Rupinta

NuGet / site data

Nuget GitHub last commit GitHub Repo stars

Details

Info

info

Name: DisposableHelpers

Disposable helpers for IDisposable and IAsyncDisposable.

Author: Clynt Neiko Rupinta

NuGet: https://www.nuget.org/packages/DisposableHelpers/

You can find more details at https://github.com/Kiryuumaru/DisposableHelpers

Source: https://github.com/Kiryuumaru/DisposableHelpers

Original Readme

note

DisposableHelpers

Disposable helpers for IDisposable and IAsyncDisposable with source generators. Also capable of both anonymous disposable and anonymous async disposable.

NuGets

NameInfo
DisposableHelpersNuGet

Installation

// Install release version
Install-Package DisposableHelpers

// Install pre-release version
Install-Package DisposableHelpers -pre

Supported frameworks

.NET Standard 2.0 and above - see https://github.com/dotnet/standard/blob/master/docs/versions.md for compatibility matrix

Usage

Disposable

using DisposableHelpers;

namespace YourNamespace
{
public class SampleDisposable : Disposable
{
private SampleUnmanagedResource resources;

protected override void Dispose(bool disposing)
{
if (disposing)
{
resources.Release();
}
base.Dispose(disposing);
}
}
}

Disposable Source Generator

using DisposableHelpers.Attributes;

namespace YourNamespace
{
[Disposable]
public partial class SampleDisposable
{
private SampleUnmanagedResource resources;

protected void Dispose(bool disposing)
{
if (disposing)
{
resources.Release();
}
base.Dispose(disposing);
}
}
}

Anonymous Disposable

using DisposableHelpers;

namespace YourNamespace
{
public static class Program
{
private static SampleUnmanagedResource resources;

public static void Main(string[] args)
{
Disposable disposable = new Disposable(disposing =>
{
if (disposing)
{
resources.Release();
}
});

disposable.Dispose();
}
}
}

AsyncDisposable

using DisposableHelpers;

namespace YourNamespace
{
public class SampleAsyncDisposable : AsyncDisposable
{
private SampleAsyncUnmanagedResource resources;

protected override async ValueTask Dispose(bool isDisposing)
{
if (isDisposing)
{
await resources.Release();
}
return base.Dispose(isDisposing);
}
}
}

AsyncDisposable Source Generator

using DisposableHelpers.Attributes;

namespace YourNamespace
{
[AsyncDisposable]
public partial class SampleAsyncDisposable
{
private SampleAsyncUnmanagedResource resources;

protected async ValueTask Dispose(bool isDisposing)
{
if (isDisposing)
{
await resources.Release();
}
return base.Dispose(isDisposing);
}
}
}

Anonymous AsyncDisposable

using DisposableHelpers;

namespace YourNamespace
{
public static class Program
{
private static SampleAsyncUnmanagedResource resources;

public static async void Main(string[] args)
{
AsyncDisposable disposable = new AsyncDisposable(async disposing =>
{
if (disposing)
{
await resources.Release();
}
});

await disposable.DisposeAsync();
}
}
}

Want To Support This Project?

All I have ever asked is to be active by submitting bugs, features, and sending those pull requests down!.

paypal

About

note

Generating boilerplate for thread safe Dispose

How to use

Example (source csproj, source files)

This is the CSharp Project that references DisposableHelpers

<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net7.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>

<PropertyGroup>
<EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
<CompilerGeneratedFilesOutputPath>$(BaseIntermediateOutputPath)\GX</CompilerGeneratedFilesOutputPath>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="DisposableHelpers" Version="1.1.16" />
</ItemGroup>

</Project>

Generated Files

Those are taken from $(BaseIntermediateOutputPath)\GX

// <auto-generated/>
#pragma warning disable
#nullable enable
namespace IDisposableGeneratorDemo
{
partial class DALDB : global::System.IDisposable
{
#nullable disable
/// <summary>
/// Finalizes an instance of the <see cref = "Disposable"/> class.
/// </summary>
[global::System.CodeDom.Compiler.GeneratedCode("DisposableHelpers.SourceGenerators.DisposableGenerator", "1.0.0.0")]
[global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage]
~DALDB()
{
Dispose(false);
}

/// <summary>
/// Gets a value indicating whether this object is in the process of disposing.
/// </summary>
[global::System.CodeDom.Compiler.GeneratedCode("DisposableHelpers.SourceGenerators.DisposableGenerator", "1.0.0.0")]
[global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage]
public bool IsDisposing => global::System.Threading.Interlocked.CompareExchange(ref disposeStage, DisposalStarted, DisposalStarted) == DisposalStarted;

/// <summary>
/// Gets a value indicating whether this object has been disposed.
/// </summary>
[global::System.CodeDom.Compiler.GeneratedCode("DisposableHelpers.SourceGenerators.DisposableGenerator", "1.0.0.0")]
[global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage]
public bool IsDisposed => global::System.Threading.Interlocked.CompareExchange(ref disposeStage, DisposalComplete, DisposalComplete) == DisposalComplete;

/// <summary>
/// Gets a value indicating whether this object has been disposed or is in the process of being disposed.
/// </summary>
[global::System.CodeDom.Compiler.GeneratedCode("DisposableHelpers.SourceGenerators.DisposableGenerator", "1.0.0.0")]
[global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage]
public bool IsDisposedOrDisposing => global::System.Threading.Interlocked.CompareExchange(ref disposeStage, DisposalNotStarted, DisposalNotStarted) != DisposalNotStarted;

/// <summary>
/// Gets the object name, for use in any <see cref = "global::System.ObjectDisposedException"/> thrown by this object.
/// </summary>
/// <remarks>
/// Subclasses can override this property if they would like more control over the object name appearing in any <see cref = "global::System.ObjectDisposedException"/>
/// thrown by this <see cref = "Disposable"/>. This can be particularly useful in debugging and diagnostic scenarios.
/// </remarks>
/// <value>
/// The object name, which defaults to the class name.
/// </value>

#nullable enable
[global::System.CodeDom.Compiler.GeneratedCode("DisposableHelpers.SourceGenerators.DisposableGenerator", "1.0.0.0")]
[global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage]
protected virtual string? ObjectName => GetType().FullName;

#nullable disable
[global::System.CodeDom.Compiler.GeneratedCode("DisposableHelpers.SourceGenerators.DisposableGenerator", "1.0.0.0")]
private const int DisposalNotStarted = 0;
[global::System.CodeDom.Compiler.GeneratedCode("DisposableHelpers.SourceGenerators.DisposableGenerator", "1.0.0.0")]
private const int DisposalStarted = 1;
[global::System.CodeDom.Compiler.GeneratedCode("DisposableHelpers.SourceGenerators.DisposableGenerator", "1.0.0.0")]
private const int DisposalComplete = 2;
// see the constants defined above for valid values
[global::System.CodeDom.Compiler.GeneratedCode("DisposableHelpers.SourceGenerators.DisposableGenerator", "1.0.0.0")]
private int disposeStage;
/// <summary>
/// Occurs when this object is about to be disposed.
/// </summary>

#nullable enable
[global::System.CodeDom.Compiler.GeneratedCode("DisposableHelpers.SourceGenerators.DisposableGenerator", "1.0.0.0")]
[global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage]
public event global::System.EventHandler? Disposing;
/// <summary>
/// Disposes of this object, if it hasn't already been disposed.
/// </summary>
[global::System.CodeDom.Compiler.GeneratedCode("DisposableHelpers.SourceGenerators.DisposableGenerator", "1.0.0.0")]
[global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage]
public void Dispose()
{
if (global::System.Threading.Interlocked.CompareExchange(ref disposeStage, DisposalStarted, DisposalNotStarted) != DisposalNotStarted)
{
return;
}

OnDisposing();
Disposing = null;
Dispose(true);
global::System.GC.SuppressFinalize(this);
global::System.Threading.Interlocked.Exchange(ref disposeStage, DisposalComplete);
}

/// <summary>
/// Verifies that this object is not in the process of disposing, throwing an exception if it is.
/// </summary>
[global::System.CodeDom.Compiler.GeneratedCode("DisposableHelpers.SourceGenerators.DisposableGenerator", "1.0.0.0")]
[global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage]
protected void VerifyNotDisposing()
{
if (IsDisposing)
{
throw new global::System.ObjectDisposedException(ObjectName);
}
}

/// <summary>
/// Verifies that this object has not been disposed, throwing an exception if it is.
/// </summary>
[global::System.CodeDom.Compiler.GeneratedCode("DisposableHelpers.SourceGenerators.DisposableGenerator", "1.0.0.0")]
[global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage]
protected void VerifyNotDisposed()
{
if (IsDisposed)
{
throw new global::System.ObjectDisposedException(ObjectName);
}
}

/// <summary>
/// Verifies that this object is not being disposed or has been disposed, throwing an exception if either of these are true.
/// </summary>
[global::System.CodeDom.Compiler.GeneratedCode("DisposableHelpers.SourceGenerators.DisposableGenerator", "1.0.0.0")]
[global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage]
protected void VerifyNotDisposedOrDisposing()
{
if (IsDisposedOrDisposing)
{
throw new global::System.ObjectDisposedException(ObjectName);
}
}

/// <summary>
/// Raises the <see cref = "Disposing"/> event.
/// </summary>
[global::System.CodeDom.Compiler.GeneratedCode("DisposableHelpers.SourceGenerators.DisposableGenerator", "1.0.0.0")]
[global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage]
protected virtual void OnDisposing()
{
Disposing?.Invoke(this, new global::System.EventArgs());
}
}
}

Useful

Download Example (.NET C#)

Share DisposableHelpers

https://ignatandrei.github.io/RSCG_Examples/v2/docs/DisposableHelpers

aaa

Category "Disposer" has the following generators:

1 BenutomoAutomaticDisposeImplSourceGenerator

2 Coplt.Dropping

3 DisposableHelpers

4 Disposer

5 IDisposableGenerator

See category

Disposer