Skip to main content

Dirge by Kazuki Kohzuki

NuGet / site data​

Nuget GitHub last commit GitHub Repo stars

Details​

Info​

info

Name: Dirge

Disposable Implementation Roslyn Generator Extension

Author: Kazuki Kohzuki

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

You can find more details at https://github.com/IkuzakIkuzok/Dirge

Source: https://github.com/IkuzakIkuzok/Dirge

Author​

note

Kazuki Kohzuki Alt text

Original Readme​

note

Dirge​

Test Version Download MIT License

Disposable Implementation Roslyn Generator Extension

Installation​

You can install the EnumSerializer from NuGet.

Usage​

Mark a class with the [AutoDispose] attribute and implement the IDisposable interface. The generator will automatically generate the implementation of the Dispose method for you.

using Dirge;

namespace Test;

[AutoDispose]
internal partial class TestClass
{
private readonly Stream _stream = new MemoryStream();
}

The generated code will look like this:

namespace Test;

partial class TestClass : IDisposable
{
private bool __generated_disposed = false;

public void Dispose()
{
Dispose(true);
global::System.GC.SuppressFinalize(this);
}

protected virtual void Dispose(bool disposing)
{
if (this.__generated_disposed) return;

try
{
if (disposing)
{
this._stream?.Dispose();
}
}
finally
{
this.__generated_disposed = true;
}
}
}

Note that this example is simplified for demonstration purposes.

To suppress the auto-generated Dispose call for a specific field, you can use the [DoNotDispose] attribute:

using Dirge;

namespace Test;

[AutoDispose]
internal partial class TestClass
{
private readonly Stream _stream1 = new MemoryStream();

[DoNotDispose]
private readonly Stream _stream2 = new MemoryStream(); // This field will not be disposed by the generated Dispose method.
}

Ref-struct is also supported, but IDisposable will not be implemented regardless of the language version.

######### Conditional disposal

Conditional disposal, which allows you to specify conditions under which a field should be disposed, is also supported. You can use the [DoNotDisposeWhen] attribute with a boolean field and a value to compare against:

using Dirge;

namespace Test;

[AutoDispose]
internal partial class TestClass
{
private readonly bool _leaveOpen;

[DoNotDisposeWhen(nameof(_leaveOpen), true)]
private readonly Stream _stream;

internal TestClass(Stream stream, bool leaveOpen)
{
this._stream = stream;
this._leaveOpen = leaveOpen;
}
}

This will prevent the generator from disposing the _stream field when the _leaveOpen field is true:

namespace Test;

partial class TestClass : IDisposable
{
private bool __generated_disposed = false;

public void Dispose()
{
Dispose(true);
global::System.GC.SuppressFinalize(this);
}

protected virtual void Dispose(bool disposing)
{
if (this.__generated_disposed) return;

try
{
if (disposing)
{
if (!this._leaveOpen)
{
this._stream?.Dispose();
}
}
}
finally
{
this.__generated_disposed = true;
}
}
}

######### Unmanaged resources

To safely release unmanaged resources, this generator also supports the implementation of a finalizer. You can specify a method to release unmanaged resources through the ReleaseUnmanagedResources option:

using Dirge;
using System.IO;

namespace Test;

[AutoDispose(ReleaseUnmanagedResources = nameof(ReleaseUnmanagedResources))]
internal sealed partial class TestClass
{
private readonly Stream _stream;

internal void ReleaseUnmanagedResources()
{
// Custom logic to release unmanaged resources
}
}

This will generate a finalizer that calls the specified method to release unmanaged resources:

namespace Test;

sealed partial class TestClass : IDisposable
{
private bool __generated_disposed = false;

public void Dispose()
{
Dispose(true);
global::System.GC.SuppressFinalize(this);
}

private void Dispose(bool disposing)
{
if (this.__generated_disposed) return;

try
{
if (disposing)
{
this._stream?.Dispose();
}

ReleaseUnmanagedResources();
}
finally
{
this.__generated_disposed = true;
}
}

~TestClass()
{
Dispose(false);
}
}
Constraints​

To generate the Dispose method, the class (or struct) must meet the following constraints:

  • It must be a non-static class.
  • It must be a partial class or struct.
  • It must not be a readonly struct.

For conditional disposal, the field specified in the nameof expression must be a boolean field. Properties and methods are not supported for the current version.

About​

note

Dirge is a Roslyn-based code generator that automatically implements the IDisposable pattern for C# classes.

Key Features:

  1. AutoDispose Attribute: Mark any partial class with [AutoDispose] to automatically generate Dispose() and Dispose(bool) methods.

  2. Automatic Field Disposal: The generator detects all disposable fields and automatically calls .Dispose() on them in the correct order.

How to use​

Example (source csproj, source files)​

This is the CSharp Project that references Dirge

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

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net10.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<PropertyGroup>
<EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
<CompilerGeneratedFilesOutputPath>$(BaseIntermediateOutputPath)\GX</CompilerGeneratedFilesOutputPath>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Dirge" Version="3.0.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
</ItemGroup>

</Project>

Generated Files​

Those are taken from $(BaseIntermediateOutputPath)\GX

// <auto-generated/>

#pragma warning disable CS0282

namespace IDisposableGeneratorDemo
{
partial class DALDB : global::System.IDisposable
{
[global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)]
[global::System.Diagnostics.DebuggerBrowsable(global::System.Diagnostics.DebuggerBrowsableState.Never)]
[global::System.Runtime.CompilerServices.CompilerGenerated]
private bool __generated_disposed = false;

public void Dispose()
{
Dispose(true);
global::System.GC.SuppressFinalize(this);
}

protected virtual void Dispose(bool disposing)
{
if (this.__generated_disposed) return;

try
{
if (disposing)
{
this.cn?.Dispose();
this.cn1?.Dispose();
}
}
finally
{
this.__generated_disposed = true;
}
}
}
}

Useful​

Download Example (.NET C#)​

Share Dirge​

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

Category "Disposer" has the following generators:​

1 BenutomoAutomaticDisposeImplSourceGenerator Nuget GitHub Repo stars 2023-08-15

2 Coplt.Dropping Nuget GitHub Repo stars 2024-08-13

3 Dirge Nuget GitHub Repo stars 2026-07-01

4 DisposableHelpers Nuget GitHub Repo stars 2023-10-09

5 Disposer Nuget GitHub Repo stars 2023-10-03

6 GenerateDispose Nuget GitHub Repo stars 2026-05-13

7 IDisposableGenerator Nuget GitHub Repo stars 2023-10-11

8 ReflectionIT.DisposeGenerator Nuget GitHub Repo stars 2026-08-19

See category​

Disposer