diff --git a/README.md b/README.md
index c99573bef..6d3581c03 100644
--- a/README.md
+++ b/README.md
@@ -1,10 +1,10 @@
-# RSCG - 278 Examples of Roslyn Source Code Generators / 16 created by Microsoft /
+# RSCG - 279 Examples of Roslyn Source Code Generators / 16 created by Microsoft /
-The RSCG_Examples repository is a comprehensive documentation system that automatically processes and showcases 278 Roslyn Source Code Generator (RSCG) examples. The system transforms individual RSCG projects into structured documentation with code examples and cross-referenced content with a searchable website and code example exports.
+The RSCG_Examples repository is a comprehensive documentation system that automatically processes and showcases 279 Roslyn Source Code Generator (RSCG) examples. The system transforms individual RSCG projects into structured documentation with code examples and cross-referenced content with a searchable website and code example exports.
This system serves as both a learning resource for .NET developers interested in source generators and an automated pipeline for maintaining up-to-date documentation about the RSCG ecosystem
-## Latest Update : 2026-08-18 => 18 August 2026
+## Latest Update : 2026-08-19 => 19 August 2026
If you want to see examples with code, please click ***[List V2](https://ignatandrei.github.io/RSCG_Examples/v2/docs/List-of-RSCG)***
@@ -24,8 +24,30 @@ If you want to be notified each time I add a new RSCG example , please click htt
## Content
-Those are the 278 Roslyn Source Code Generators that I have tested you can see and download source code example.
+Those are the 279 Roslyn Source Code Generators that I have tested you can see and download source code example.
( including 16 from Microsoft )
+### 279. [ReflectionIT.DisposeGenerator](https://ignatandrei.github.io/RSCG_Examples/v2/docs/ReflectionIT.DisposeGenerator) , in the [Disposer](https://ignatandrei.github.io/RSCG_Examples/v2/docs/rscg-examples#disposer) category
+
+Generated on : 2026-08-19 => 19 August 2026
+
+
+ Expand
+
+
+
+Author: Fons Sonnemans
+
+Package Description
+
+Nuget: [https://www.nuget.org/packages/ReflectionIT.DisposeGenerator/](https://www.nuget.org/packages/ReflectionIT.DisposeGenerator/)
+
+
+Link: [https://ignatandrei.github.io/RSCG_Examples/v2/docs/ReflectionIT.DisposeGenerator](https://ignatandrei.github.io/RSCG_Examples/v2/docs/ReflectionIT.DisposeGenerator)
+
+Source: [https://github.com/sonnemaf/ReflectionIT.DisposeGenerator](https://github.com/sonnemaf/ReflectionIT.DisposeGenerator)
+
+
+
### 278. [Atulin.AutoDbSet](https://ignatandrei.github.io/RSCG_Examples/v2/docs/Atulin.AutoDbSet) , in the [EntityFramework](https://ignatandrei.github.io/RSCG_Examples/v2/docs/rscg-examples#entityframework) category
Generated on : 2026-08-18 => 18 August 2026
diff --git a/later.md b/later.md
index 7c77384b0..c482172ea 100644
--- a/later.md
+++ b/later.md
@@ -1,6 +1,6 @@
# Just later
-## Latest Update : 2026-08-18 => 18 August 2026
+## Latest Update : 2026-08-19 => 19 August 2026
diff --git a/v2/Generator/all.csv b/v2/Generator/all.csv
index 348301fff..7e51dc849 100644
--- a/v2/Generator/all.csv
+++ b/v2/Generator/all.csv
@@ -277,3 +277,4 @@ Nr,Key,Source,Category
276,TinyBDD.MSTest, https://github.com/JerrettDavis/TinyBDD,Tests
277,Bennewitz.Ninja.AutoVersioning, https://github.com/JanusMael/Bennewitz.Ninja.AutoVersioning,EnhancementProject
278,Atulin.AutoDbSet, https://github.com/Atulin/AutoDbSet,EntityFramework
+279,ReflectionIT.DisposeGenerator, https://github.com/sonnemaf/ReflectionIT.DisposeGenerator,Disposer
diff --git a/v2/RSCGExamplesData/GeneratorDataRec.json b/v2/RSCGExamplesData/GeneratorDataRec.json
index d6f25daea..e658bbcb6 100644
--- a/v2/RSCGExamplesData/GeneratorDataRec.json
+++ b/v2/RSCGExamplesData/GeneratorDataRec.json
@@ -1684,5 +1684,11 @@
"Category": 48,
"dtStart": "2026-08-18T00:00:00",
"show": true
+ },
+ {
+ "ID": "ReflectionIT.DisposeGenerator",
+ "Category": 18,
+ "dtStart": "2026-08-19T00:00:00",
+ "show": true
}
]
\ No newline at end of file
diff --git a/v2/book/examples/ReflectionIT.DisposeGenerator.html b/v2/book/examples/ReflectionIT.DisposeGenerator.html
new file mode 100644
index 000000000..a094f2948
--- /dev/null
+++ b/v2/book/examples/ReflectionIT.DisposeGenerator.html
@@ -0,0 +1,59 @@
+
+
RSCG nr 279 : ReflectionIT.DisposeGenerator
+
+Info
+Nuget : https://www.nuget.org/packages/ReflectionIT.DisposeGenerator/
+
+You can find more details at : https://github.com/sonnemaf/ReflectionIT.DisposeGenerator
+
+Author :Fons Sonnemans
+
+Source: https://github.com/sonnemaf/ReflectionIT.DisposeGenerator
+
+About
+
+Automatically implements the IDisposable pattern for classes that contain disposable fields.
+
+
+ How to use
+
+
+
+
+This was for me the starting code
+
+
+ I have coded the file Program.cs
+
+
+
+
+
+ I have coded the file ConnectionDB.cs
+
+
+
+ And here are the generated files
+
+
+ The file generated is IDisposableGeneratorDemo.DALDB.g.cs
+
+
+
+
+ You can download the code and this page as pdf from
+
+ https://ignatandrei.github.io/RSCG_Examples/v2/docs/ReflectionIT.DisposeGenerator
+
+
+
+
+
+ You can see the whole list at
+
+ https://ignatandrei.github.io/RSCG_Examples/v2/docs/List-of-RSCG
+
+
+
diff --git a/v2/book/list.html b/v2/book/list.html
index 07f177f04..e62f28c0d 100644
--- a/v2/book/list.html
+++ b/v2/book/list.html
@@ -17,7 +17,7 @@
-This is the list of 278 RSCG with examples =>
+This is the list of 279 RSCG with examples =>
diff --git a/v2/book/pandocHTML.yaml b/v2/book/pandocHTML.yaml
index ad1a40133..1b8dd70fa 100644
--- a/v2/book/pandocHTML.yaml
+++ b/v2/book/pandocHTML.yaml
@@ -292,6 +292,7 @@ input-files:
- examples/TinyBDD.MSTest.html
- examples/Bennewitz.Ninja.AutoVersioning.html
- examples/Atulin.AutoDbSet.html
+- examples/ReflectionIT.DisposeGenerator.html
# or you may use input-file: with a single value
# defaults:
diff --git a/v2/docFind.json b/v2/docFind.json
index f8690632d..c2e276b50 100644
--- a/v2/docFind.json
+++ b/v2/docFind.json
@@ -1666,5 +1666,11 @@
"category": "EntityFramework",
"href": "/RSCG_Examples/v2/docs/Atulin.AutoDbSet/",
"body": "Package Description"
+ },
+ {
+ "title": "ReflectionIT.DisposeGenerator",
+ "category": "Disposer",
+ "href": "/RSCG_Examples/v2/docs/ReflectionIT.DisposeGenerator/",
+ "body": "Package Description"
}
]
\ No newline at end of file
diff --git a/v2/rscg_examples/ReflectionIT.DisposeGenerator/description.json b/v2/rscg_examples/ReflectionIT.DisposeGenerator/description.json
new file mode 100644
index 000000000..7827615f6
--- /dev/null
+++ b/v2/rscg_examples/ReflectionIT.DisposeGenerator/description.json
@@ -0,0 +1,22 @@
+{
+ "generator":{
+ "name":"ReflectionIT.DisposeGenerator",
+ "nuget":[
+ "https://www.nuget.org/packages/ReflectionIT.DisposeGenerator/"
+ ],
+ "link":"https://github.com/sonnemaf/ReflectionIT.DisposeGenerator",
+ "author":"Fons Sonnemans",
+ "source":"https://github.com/sonnemaf/ReflectionIT.DisposeGenerator"
+ },
+ "data":{
+ "goodFor":["Automatically implements the IDisposable pattern for classes that contain disposable fields."],
+ "csprojDemo":"IDisp.csproj",
+ "csFiles":["Program.cs","DALDB.cs","ConnectionDB.cs"],
+ "excludeDirectoryGenerated":[""],
+ "includeAdditionalFiles":[""]
+ },
+ "links":{
+ "blog":"",
+ "video":""
+ }
+}
\ No newline at end of file
diff --git a/v2/rscg_examples/ReflectionIT.DisposeGenerator/nuget.txt b/v2/rscg_examples/ReflectionIT.DisposeGenerator/nuget.txt
new file mode 100644
index 000000000..882e74f60
--- /dev/null
+++ b/v2/rscg_examples/ReflectionIT.DisposeGenerator/nuget.txt
@@ -0,0 +1 @@
+Package Description
\ No newline at end of file
diff --git a/v2/rscg_examples/ReflectionIT.DisposeGenerator/readme.txt b/v2/rscg_examples/ReflectionIT.DisposeGenerator/readme.txt
new file mode 100644
index 000000000..f1e23e917
--- /dev/null
+++ b/v2/rscg_examples/ReflectionIT.DisposeGenerator/readme.txt
@@ -0,0 +1,506 @@
+# ReflectionIT.DisposeGenerator
+
+A source generator package that implements the dispose and async dispose patterns.
+
+- https://docs.microsoft.com/en-us/dotnet/standard/design-guidelines/dispose-pattern
+- https://docs.microsoft.com/en-us/dotnet/standard/garbage-collection/implementing-dispose
+- https://learn.microsoft.com/en-us/dotnet/standard/garbage-collection/implementing-disposeasync
+
+## NuGet package
+
+| Package | Version |
+| ------ | ------ |
+| ReflectionIT.DisposeGenerator | [](https://www.nuget.org/packages/ReflectionIT.DisposeGenerator/) |
+
+## Installation
+
+```xml
+
+```
+
+## Quick start
+
+Annotate a **partial** class or struct with the `Disposable` attribute and mark disposable fields or properties with `Dispose`.
+
+```cs
+using System;
+using System.IO;
+using ReflectionIT.DisposeGenerator.Attributes;
+
+[Disposable]
+public partial class LogWriter : IDisposable {
+
+ [Dispose]
+ private readonly StreamWriter _streamWriter;
+
+ public LogWriter(string path) => _streamWriter = new StreamWriter(path);
+
+ public void WriteLine(string text) {
+ ThrowIfDisposed();
+ _streamWriter.WriteLine($"{DateTime.Now}\t{text}");
+ }
+}
+```
+
+The generator creates the dispose members for the annotated type, including `_isDisposed`, an `IsDisposed` property, and `ThrowIfDisposed()` by default.
+
+## Requirements and diagnostics
+
+- The annotated type must be `partial`.
+- `[Disposable]` can be applied to classes and structs.
+- `[Dispose]` and `[AsyncDispose]` can be applied to fields and properties.
+- The generator emits `RITDG001` when a type annotated with `[Disposable]` is not declared `partial`.
+- Members annotated with `[Dispose]` or `[AsyncDispose]` must support the generated dispose call pattern. Otherwise the generated code can produce compiler errors.
+
+### RITDG001
+
+`RITDG001`: Type `'{typeName}'` is annotated with `[Disposable]` and must be declared partial for ReflectionIT.DisposeGenerator to generate code.
+
+## Attribute reference
+
+### `DisposableAttribute`
+
+| Property | Default | Description |
+| --- | --- | --- |
+| `OverrideDispose` | `false` | Generates `Dispose(bool)` as an override instead of generating a public `Dispose()` method. |
+| `OverrideDisposeAsyncCore` | `false` | Generates `DisposeAsyncCore()` as an override instead of generating a public `DisposeAsync()` method. |
+| `GenerateThrowIfDisposed` | `true` | Generates `ThrowIfDisposed()` for guarding public instance members. |
+| `ExplicitInterfaceImplementation` | `false` | Generates explicit `IDisposable.Dispose()` and `IAsyncDisposable.DisposeAsync()` implementations when applicable. |
+| `IsThreadSafe` | `false` | Uses thread-safe disposal state transitions via `Interlocked.CompareExchange`. |
+| `HasUnmanagedResources` | `false` | Adds a finalizer and `ReleaseUnmanagedResources()` partial method support. |
+
+### `DisposeAttribute`
+
+| Property | Default | Description |
+| --- | --- | --- |
+| `SetToNull` | `false` | Sets the annotated field or property to `null` after disposal. |
+
+### `AsyncDisposeAttribute`
+
+| Property | Default | Description |
+| --- | --- | --- |
+| `SetToNull` | `false` | Sets the annotated field or property to `null` after asynchronous disposal. |
+| `ConfigureAwait` | `true` | Controls the `ConfigureAwait(...)` value used for generated async disposal calls. |
+
+## What gets generated
+
+Depending on the options and the annotated members, the generator can create:
+
+- `Dispose()`
+- `Dispose(bool)`
+- `DisposeAsync()`
+- `DisposeAsyncCore()`
+- `IsDisposed`
+- `ThrowIfDisposed()`
+- `_isDisposed`
+- a finalizer
+- `ReleaseUnmanagedResources()`
+
+## Recommended use of `ThrowIfDisposed`
+
+Call `ThrowIfDisposed()` at the start of public instance members that depend on resources managed by the generated dispose pattern. The generated method uses the generated `IsDisposed` property, so derived types can customize disposed-state checks through `IsDisposed` instead of overriding `ThrowIfDisposed()`.
+
+```cs
+using ReflectionIT.DisposeGenerator.Attributes;
+
+[Disposable]
+public partial class LogWriter : IDisposable {
+
+ [Dispose]
+ private readonly StreamWriter _streamWriter;
+
+ public LogWriter(string path) => _streamWriter = new StreamWriter(path);
+
+ public void WriteLine(string text) {
+ ThrowIfDisposed();
+ _streamWriter.WriteLine($"{DateTime.Now}\t{text}");
+ }
+}
+```
+
+This helps fail fast with an `ObjectDisposedException` when the instance is used after it has been disposed.
+
+## `SetToNull` usage
+
+Use `SetToNull` when the property or field should be set to `null` after disposal.
+
+```cs
+using ReflectionIT.DisposeGenerator.Attributes;
+
+[Disposable]
+public partial class LogWriter : IDisposable {
+
+ [Dispose(SetToNull = true)]
+ private StreamWriter StreamWriter { get; set; }
+
+ public LogWriter(string path) => StreamWriter = new StreamWriter(path);
+
+ public void WriteLine(string text) {
+ ThrowIfDisposed();
+ StreamWriter.WriteLine($"{DateTime.Now}\t{text}");
+ }
+}
+```
+
+This generates the following partial class, which disposes the `StreamWriter` property and sets it to `null`.
+
+```cs
+partial class LogWriter
+{
+ ///
+ /// Releases all resources used by the current instance.
+ ///
+ public void Dispose() {
+ Dispose(disposing: true);
+ global::System.GC.SuppressFinalize(this);
+ }
+
+ ///
+ /// Tracks whether the current instance has been disposed. This field must not be modified manually.
+ ///
+ private bool _isDisposed;
+
+ ///
+ /// Gets a value indicating whether the current instance has been disposed.
+ ///
+ protected virtual bool IsDisposed => _isDisposed;
+
+ ///
+ /// Throws an exception if the current instance has been disposed.
+ ///
+ protected void ThrowIfDisposed() {
+ if (IsDisposed) {
+ throw new global::System.ObjectDisposedException(nameof(LogWriter));
+ }
+ }
+
+ ///
+ /// Releases the unmanaged resources used by the current instance and optionally releases the managed resources.
+ ///
+ /// "true" to release managed resources; otherwise, "false".
+ protected virtual void Dispose(bool disposing) {
+ if (_isDisposed) {
+ return;
+ }
+ _isDisposed = true;
+ if (disposing) {
+ this.StreamWriter?.Dispose();
+ }
+ StreamWriter = null;
+ }
+
+}
+```
+
+## Async dispose
+
+Use `AsyncDispose` for fields or properties that support `DisposeAsync()`.
+
+```cs
+using System;
+using System.IO;
+using ReflectionIT.DisposeGenerator.Attributes;
+
+[Disposable]
+public partial class LogWriter : IAsyncDisposable {
+
+ [AsyncDispose]
+ private readonly StreamWriter _streamWriter;
+
+ public LogWriter(string path) => _streamWriter = new StreamWriter(path);
+}
+```
+
+This generates `DisposeAsync()` and `DisposeAsyncCore()`. If the same member also has `[Dispose]`, the generator supports both sync and async cleanup patterns.
+
+```cs
+partial class LogWriter
+{
+ ///
+ /// Asynchronously releases all resources used by the current instance.
+ ///
+ ///
+ /// A task that represents the asynchronous dispose operation.
+ ///
+ public async global::System.Threading.Tasks.ValueTask DisposeAsync() {
+ await DisposeAsyncCore().ConfigureAwait(false);
+ global::System.GC.SuppressFinalize(this);
+ }
+
+ ///
+ /// Tracks whether the current instance has been disposed. This field must not be modified manually.
+ ///
+ private bool _isDisposed;
+
+ ///
+ /// Gets a value indicating whether the current instance has been disposed.
+ ///
+ protected virtual bool IsDisposed => _isDisposed;
+
+ ///
+ /// Throws an exception if the current instance has been disposed.
+ ///
+ protected void ThrowIfDisposed() {
+ if (IsDisposed) {
+ throw new global::System.ObjectDisposedException(nameof(LogWriter));
+ }
+ }
+
+ ///
+ /// Asynchronously releases the resources used by the current instance.
+ ///
+ ///
+ /// A task that represents the asynchronous dispose operation.
+ ///
+ protected virtual async global::System.Threading.Tasks.ValueTask DisposeAsyncCore() {
+ if (_isDisposed) {
+ return;
+ }
+ _isDisposed = true;
+ if (this._streamWriter != null) {
+ await this._streamWriter.DisposeAsync().ConfigureAwait(false);
+ }
+ }
+
+}
+```
+
+## Implement the dispose pattern for a derived class
+
+A class derived from a class that already implements `IDisposable` should not implement `IDisposable` again, because the base implementation of `IDisposable.Dispose` is inherited by derived classes.
+
+Set `OverrideDispose = true` for the derived partial class. In that case, the public parameterless `Dispose()` method is not generated, and the protected `Dispose(bool)` method is generated as an override instead.
+
+```cs
+[Disposable(OverrideDispose = true)]
+public partial class SecondLogWriter : LogWriter {
+
+ [Dispose]
+ private StreamWriter SecondStreamWriter { get; }
+
+ public SecondLogWriter(string path) : base(path) => SecondStreamWriter = new StreamWriter(path + "2");
+
+ public override void WriteLine(string text) {
+ base.WriteLine(text);
+ SecondStreamWriter.WriteLine($"{DateTime.Now}\t{text.ToUpper()}");
+ }
+}
+```
+
+This generates the following partial class, which disposes the `SecondStreamWriter` property.
+
+```cs
+partial class SecondLogWriter
+{
+ ///
+ /// Tracks whether the current instance has been disposed. This field must not be modified manually.
+ ///
+ private bool _isDisposed;
+
+ ///
+ /// Gets a value indicating whether the current instance has been disposed.
+ ///
+ protected override bool IsDisposed => _isDisposed || base.IsDisposed;
+
+ ///
+ /// Throws an exception if the current instance has been disposed.
+ ///
+ protected void ThrowIfDisposed() {
+ if (IsDisposed) {
+ throw new global::System.ObjectDisposedException(nameof(SecondLogWriter));
+ }
+ }
+
+ ///
+ /// Releases the unmanaged resources used by the current instance and optionally releases the managed resources.
+ ///
+ /// "true" to release managed resources; otherwise, "false".
+ protected override void Dispose(bool disposing) {
+ if (_isDisposed) {
+ return;
+ }
+ _isDisposed = true;
+ if (disposing) {
+ this.SecondStreamWriter?.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+}
+```
+
+## Unmanaged resources
+
+Set `HasUnmanagedResources = true` to include unmanaged resource cleanup support.
+Then implement the partial method `ReleaseUnmanagedResources()`, which releases the unmanaged resource.
+
+If you need to work with unmanaged resources, it is strongly recommended to wrap the unmanaged `IntPtr` handle in a [SafeHandle](https://learn.microsoft.com/en-us/dotnet/standard/garbage-collection/implementing-dispose#safe-handles).
+
+```cs
+[Disposable(HasUnmanagedResources = true)]
+public partial class LogWriterWithAnExtraIntPtr : IDisposable {
+
+ private readonly IntPtr _pointer;
+
+ [Dispose]
+ private StreamWriter StreamWriter { get; }
+
+ public LogWriterWithAnExtraIntPtr(string path) {
+ StreamWriter = new StreamWriter(path);
+ _pointer = Marshal.AllocHGlobal(cb: 128);
+ }
+
+ public void WriteLine(string text) => StreamWriter.WriteLine($"{DateTime.Now}\t{text}");
+
+ protected virtual partial void ReleaseUnmanagedResources() => Marshal.FreeHGlobal(_pointer);
+}
+```
+
+This generates the following partial class with a finalizer and a partial method named `ReleaseUnmanagedResources()` that you must implement.
+
+```cs
+partial class LogWriterWithAnExtraIntPtr
+{
+ ///
+ /// Releases all resources used by the current instance.
+ ///
+ public void Dispose() {
+ Dispose(disposing: true);
+ global::System.GC.SuppressFinalize(this);
+ }
+
+ ///
+ /// Releases unmanaged resources held by the current instance.
+ ///
+ ~LogWriterWithAnExtraIntPtr() {
+ Dispose(disposing: false);
+ }
+
+ ///
+ /// Releases unmanaged resources held by the current instance.
+ ///
+ protected virtual partial void ReleaseUnmanagedResources();
+
+ ///
+ /// Tracks whether the current instance has been disposed. This field must not be modified manually.
+ ///
+ private bool _isDisposed;
+
+ ///
+ /// Gets a value indicating whether the current instance has been disposed.
+ ///
+ protected virtual bool IsDisposed => _isDisposed;
+
+ ///
+ /// Throws an exception if the current instance has been disposed.
+ ///
+ protected void ThrowIfDisposed() {
+ if (IsDisposed) {
+ throw new global::System.ObjectDisposedException(nameof(LogWriterWithAnExtraIntPtr));
+ }
+ }
+
+ ///
+ /// Releases the unmanaged resources used by the current instance and optionally releases the managed resources.
+ ///
+ /// "true" to release managed resources; otherwise, "false".
+ protected virtual void Dispose(bool disposing) {
+ if (_isDisposed) {
+ return;
+ }
+ _isDisposed = true;
+ if (disposing) {
+ this.StreamWriter?.Dispose();
+ }
+ ReleaseUnmanagedResources();
+ }
+
+}
+```
+
+## Thread-safe disposal
+
+Use `IsThreadSafe = true` to ensure thread-safe disposal via `Interlocked.CompareExchange`.
+
+```cs
+[Disposable(IsThreadSafe = true)]
+public partial class LogWriter : IDisposable {
+
+ [Dispose]
+ private readonly StreamWriter _streamWriter;
+
+ public LogWriter(string path) => _streamWriter = new StreamWriter(path);
+
+ public void WriteLine(string text) => _streamWriter.WriteLine($"{DateTime.Now}\t{text}");
+}
+```
+
+This generates the following partial class, which uses `Interlocked.CompareExchange` to ensure thread-safe disposal.
+
+```cs
+partial class LogWriter
+{
+ ///
+ /// Releases all resources used by the current instance.
+ ///
+ public void Dispose() {
+ Dispose(disposing: true);
+ global::System.GC.SuppressFinalize(this);
+ }
+
+ ///
+ /// Detects redundant Dispose() calls in a thread-safe manner. _isDisposed == 0 means Dispose(bool) has not been called yet, and _isDisposed == 1 means Dispose(bool) has already been called. This field must not be modified manually.
+ ///
+ private int _isDisposed;
+
+ ///
+ /// Gets a value indicating whether the current instance has been disposed.
+ ///
+ protected virtual bool IsDisposed => _isDisposed != 0;
+
+ ///
+ /// Throws an exception if the current instance has been disposed.
+ ///
+ protected void ThrowIfDisposed() {
+ if (IsDisposed) {
+ throw new global::System.ObjectDisposedException(nameof(LogWriter));
+ }
+ }
+
+ ///
+ /// Releases the unmanaged resources used by the current instance and optionally releases the managed resources.
+ ///
+ /// "true" to release managed resources; otherwise, "false".
+ protected virtual void Dispose(bool disposing) {
+ if (global::System.Threading.Interlocked.CompareExchange(ref _isDisposed, 1, 0) != 0) {
+ return;
+ }
+ if (disposing) {
+ this._streamWriter?.Dispose();
+ }
+ }
+
+}
+```
+
+## Troubleshooting
+
+### Why do I get `RITDG001`?
+
+The type marked with `[Disposable]` is not declared `partial`. Add the `partial` keyword to the class or struct declaration.
+
+### Why do I get compiler errors for `Dispose()` or `DisposeAsync()` on an annotated member?
+
+The generator emits calls to `Dispose()` for `[Dispose]` members and `DisposeAsync()` for `[AsyncDispose]` members. Make sure the annotated member supports the corresponding API.
+
+### Why was no code generated?
+
+Common reasons:
+
+- the type is not `partial`
+- no fields or properties were annotated with `[Dispose]` or `[AsyncDispose]`
+- the type only has invalid attribute usage that prevents successful compilation
+
+## License
+
+This project is licensed under the MIT License. See the [LICENSE](LICENSE.txt) file for details.
diff --git a/v2/rscg_examples/ReflectionIT.DisposeGenerator/src/.tours/ReflectionIT.DisposeGenerator.tour b/v2/rscg_examples/ReflectionIT.DisposeGenerator/src/.tours/ReflectionIT.DisposeGenerator.tour
new file mode 100644
index 000000000..3601ad15d
--- /dev/null
+++ b/v2/rscg_examples/ReflectionIT.DisposeGenerator/src/.tours/ReflectionIT.DisposeGenerator.tour
@@ -0,0 +1,36 @@
+
+{
+ "$schema": "https://aka.ms/codetour-schema",
+ "title": "ReflectionIT.DisposeGenerator",
+ "steps":
+ [
+ {
+ "file": "IDisp/IDisp.csproj",
+ "description": "First, we add Nuget [ReflectionIT.DisposeGenerator](https://www.nuget.org/packages/ReflectionIT.DisposeGenerator/) in csproj ",
+ "pattern": "ReflectionIT.DisposeGenerator"
+ }
+
+ ,{
+ "file": "IDisp/ConnectionDB.cs",
+ "description": "File ConnectionDB.cs ",
+ "pattern": "this is the code"
+ }
+
+ ,{
+ "file": "IDisp/Program.cs",
+ "description": "File Program.cs \r\n>> dotnet run --project IDisp/IDisp.csproj ",
+ "pattern": "this is the code"
+ }
+
+
+ ,{
+ "file": "IDisp/obj/GX/ReflectionIT.DisposeGenerator/ReflectionIT.DisposeGenerator.SourceGenerator/IDisposableGeneratorDemo.DALDB.g.cs",
+ "description": "Generated File 1 from 1 : IDisposableGeneratorDemo.DALDB.g.cs ",
+ "line": 1
+ }
+
+ ],
+
+ "ref": "main"
+
+}
\ No newline at end of file
diff --git a/v2/rscg_examples/ReflectionIT.DisposeGenerator/src/IDisp.sln b/v2/rscg_examples/ReflectionIT.DisposeGenerator/src/IDisp.sln
new file mode 100644
index 000000000..ad2677ba6
--- /dev/null
+++ b/v2/rscg_examples/ReflectionIT.DisposeGenerator/src/IDisp.sln
@@ -0,0 +1,25 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 17
+VisualStudioVersion = 17.6.33829.357
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "IDisp", "IDisp\IDisp.csproj", "{6237DD9A-6211-4046-97B4-754E12478992}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {6237DD9A-6211-4046-97B4-754E12478992}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {6237DD9A-6211-4046-97B4-754E12478992}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {6237DD9A-6211-4046-97B4-754E12478992}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {6237DD9A-6211-4046-97B4-754E12478992}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {81F892FB-0998-4DEA-92E1-55B8EECB0608}
+ EndGlobalSection
+EndGlobal
diff --git a/v2/rscg_examples/ReflectionIT.DisposeGenerator/src/IDisp/ConnectionDB.cs b/v2/rscg_examples/ReflectionIT.DisposeGenerator/src/IDisp/ConnectionDB.cs
new file mode 100644
index 000000000..2c24c9fc3
--- /dev/null
+++ b/v2/rscg_examples/ReflectionIT.DisposeGenerator/src/IDisp/ConnectionDB.cs
@@ -0,0 +1,13 @@
+namespace IDisposableGeneratorDemo;
+class ConnectionDB : IDisposable
+{
+ static int count = 0;
+ public ConnectionDB()
+ {
+ Interlocked.Increment(ref count);
+ }
+ public void Dispose()
+ {
+ Console.WriteLine($"disposing connectiondb {Interlocked.Decrement(ref count)}");
+ }
+}
diff --git a/v2/rscg_examples/ReflectionIT.DisposeGenerator/src/IDisp/DALDB.cs b/v2/rscg_examples/ReflectionIT.DisposeGenerator/src/IDisp/DALDB.cs
new file mode 100644
index 000000000..858b553a3
--- /dev/null
+++ b/v2/rscg_examples/ReflectionIT.DisposeGenerator/src/IDisp/DALDB.cs
@@ -0,0 +1,19 @@
+using ReflectionIT.DisposeGenerator.Attributes;
+
+namespace IDisposableGeneratorDemo;
+
+[Disposable]
+partial class DALDB :IDisposable
+{
+ [Dispose]
+ private ConnectionDB cn;
+ [Dispose]
+ private ConnectionDB cn1;
+
+ public DALDB()
+ {
+ cn = new ConnectionDB();
+ cn1=new ConnectionDB();
+ }
+
+}
diff --git a/v2/rscg_examples/ReflectionIT.DisposeGenerator/src/IDisp/IDisp.csproj b/v2/rscg_examples/ReflectionIT.DisposeGenerator/src/IDisp/IDisp.csproj
new file mode 100644
index 000000000..56c0be781
--- /dev/null
+++ b/v2/rscg_examples/ReflectionIT.DisposeGenerator/src/IDisp/IDisp.csproj
@@ -0,0 +1,17 @@
+
+
+
+ Exe
+ net10.0
+ enable
+ enable
+
+
+ true
+ $(BaseIntermediateOutputPath)\GX
+
+
+
+
+
+
diff --git a/v2/rscg_examples/ReflectionIT.DisposeGenerator/src/IDisp/Program.cs b/v2/rscg_examples/ReflectionIT.DisposeGenerator/src/IDisp/Program.cs
new file mode 100644
index 000000000..bcce4b491
--- /dev/null
+++ b/v2/rscg_examples/ReflectionIT.DisposeGenerator/src/IDisp/Program.cs
@@ -0,0 +1,7 @@
+using IDisposableGeneratorDemo;
+// https://github.com/sonnemaf/ReflectionIT.DisposeGenerator
+using (var db = new DALDB())
+{
+ Console.WriteLine("before releasing");
+}
+Console.WriteLine("after releasing");
\ No newline at end of file
diff --git a/v2/rscg_examples/ReflectionIT.DisposeGenerator/video.json b/v2/rscg_examples/ReflectionIT.DisposeGenerator/video.json
new file mode 100644
index 000000000..d23e28a6c
--- /dev/null
+++ b/v2/rscg_examples/ReflectionIT.DisposeGenerator/video.json
@@ -0,0 +1,39 @@
+{
+ "scriptName": "ReflectionIT.DisposeGenerator",
+ "steps":
+[
+ {"typeStep":"exec","arg":"clipchamp.exe launch"},
+ {"typeStep":"text","arg": "Welcome to Roslyn Examples"},
+ {"typeStep":"text","arg":"If you want to see more examples , see List Of RSCG"},
+ {"typeStep":"browser","arg":"https://ignatandrei.github.io/RSCG_Examples/v2/docs/List-of-RSCG"},
+ {"typeStep":"text","arg": "My name is Andrei Ignat and I am deeply fond of Roslyn Source Code Generator. "},
+
+{"typeStep":"text","arg": "Today I will present ReflectionIT.DisposeGenerator . Automatically implements the IDisposable pattern for classes that contain disposable fields. ."},
+{"typeStep":"browser","arg":"https://www.nuget.org/packages/ReflectionIT.DisposeGenerator/"},
+{"typeStep":"text","arg": "The whole example is here"},
+{"typeStep":"browser","arg":"https://ignatandrei.github.io/RSCG_Examples/v2/docs/ReflectionIT.DisposeGenerator"},
+{"typeStep":"text","arg": "You can download the code from here"},
+{"typeStep":"browser","arg":"https://ignatandrei.github.io/RSCG_Examples/v2/docs/ReflectionIT.DisposeGenerator#download-example-net--c-"},
+{"typeStep":"text","arg":"Here is the code downloaded "},
+{"typeStep":"exec","arg":"explorer.exe /select,D:\\gth\\RSCG_Examples\\v2\\rscg_examples\\ReflectionIT.DisposeGenerator\\src\\IDisp.sln"},
+{"typeStep":"text","arg": "So , let's start the project with Visual Studio Code "},
+{"typeStep":"stepvscode","arg": "-n D:\\gth\\RSCG_Examples\\v2\\rscg_examples\\ReflectionIT.DisposeGenerator\\src"},
+
+{"typeStep":"text","arg": "To use it ,you will put the Nuget ReflectionIT.DisposeGenerator into the csproj "},
+
+{"typeStep":"stepvscode","arg": "-r -g D:\\gth\\RSCG_Examples\\v2\\rscg_examples\\ReflectionIT.DisposeGenerator\\src\\IDisp\\IDisp.csproj"},
+
+{"typeStep":"text","arg": "And now I will show you an example of using ReflectionIT.DisposeGenerator"},
+
+{"typeStep":"hide","arg": "now execute the tour in VSCode"},
+{"typeStep":"tour", "arg": "src/.tours/"},
+{"typeStep":"text","arg":" And I will execute the project"},
+{"typeStep":"showproj", "arg":"IDisp.csproj"},
+{"typeStep":"text","arg":" This concludes the project"},
+{"typeStep":"waitseconds","arg":"30"},
+{"typeStep":"text","arg": "Remember, you can download the code from here"},
+{"typeStep":"browser","arg":"https://ignatandrei.github.io/RSCG_Examples/v2/docs/ReflectionIT.DisposeGenerator#download-example-net--c-",
+SpeakTest=" "},
+{"typeStep":"waitseconds","arg":"30"},
+]
+}
diff --git a/v2/rscg_examples_site/docs/Authors/Fons_Sonnemans.md b/v2/rscg_examples_site/docs/Authors/Fons_Sonnemans.md
index f0e1ad458..690cbf5c7 100644
--- a/v2/rscg_examples_site/docs/Authors/Fons_Sonnemans.md
+++ b/v2/rscg_examples_site/docs/Authors/Fons_Sonnemans.md
@@ -1,7 +1,9 @@
# Author : Fons Sonnemans
-Number RSCG: 1
+Number RSCG: 2
1 [Comparison](/docs/Comparison) [](https://www.nuget.org/packages/ReflectionIT.ComparisonOperatorsGenerator/)  2025-05-25
+ 2 [ReflectionIT.DisposeGenerator](/docs/ReflectionIT.DisposeGenerator) [](https://www.nuget.org/packages/ReflectionIT.DisposeGenerator/)  2026-08-19
+
diff --git a/v2/rscg_examples_site/docs/Categories/Disposer.md b/v2/rscg_examples_site/docs/Categories/Disposer.md
index d5225746d..c2c207532 100644
--- a/v2/rscg_examples_site/docs/Categories/Disposer.md
+++ b/v2/rscg_examples_site/docs/Categories/Disposer.md
@@ -1,6 +1,6 @@
Disposer
-Number RSCG: 7
+Number RSCG: 8
1 [BenutomoAutomaticDisposeImplSourceGenerator](/docs/BenutomoAutomaticDisposeImplSourceGenerator) [](https://www.nuget.org/packages/Benutomo.AutomaticDisposeImpl.SourceGenerator/)  2023-08-15
@@ -15,4 +15,6 @@ Number RSCG: 7
6 [GenerateDispose](/docs/GenerateDispose) [](https://www.nuget.org/packages/GenerateDispose/)  2026-05-13
7 [IDisposableGenerator](/docs/IDisposableGenerator) [](https://www.nuget.org/packages/IDisposableGenerator/)  2023-10-11
+
+ 8 [ReflectionIT.DisposeGenerator](/docs/ReflectionIT.DisposeGenerator) [](https://www.nuget.org/packages/ReflectionIT.DisposeGenerator/)  2026-08-19
\ No newline at end of file
diff --git a/v2/rscg_examples_site/docs/Categories/_PrimitiveDisposer.mdx b/v2/rscg_examples_site/docs/Categories/_PrimitiveDisposer.mdx
index 28fda18bb..72fbf4c1e 100644
--- a/v2/rscg_examples_site/docs/Categories/_PrimitiveDisposer.mdx
+++ b/v2/rscg_examples_site/docs/Categories/_PrimitiveDisposer.mdx
@@ -14,6 +14,8 @@
7 [IDisposableGenerator](/docs/IDisposableGenerator) [](https://www.nuget.org/packages/IDisposableGenerator/)  2023-10-11
+ 8 [ReflectionIT.DisposeGenerator](/docs/ReflectionIT.DisposeGenerator) [](https://www.nuget.org/packages/ReflectionIT.DisposeGenerator/)  2026-08-19
+
### See category
[Disposer](/docs/Categories/Disposer)
diff --git a/v2/rscg_examples_site/docs/RSCG-Examples/ReflectionIT.DisposeGenerator.md b/v2/rscg_examples_site/docs/RSCG-Examples/ReflectionIT.DisposeGenerator.md
new file mode 100644
index 000000000..fe299cf86
--- /dev/null
+++ b/v2/rscg_examples_site/docs/RSCG-Examples/ReflectionIT.DisposeGenerator.md
@@ -0,0 +1,747 @@
+---
+sidebar_position: 2790
+title: 279 - ReflectionIT.DisposeGenerator
+description: Automatically implements the IDisposable pattern for classes that contain disposable fields.
+slug: /ReflectionIT.DisposeGenerator
+---
+import Tabs from '@theme/Tabs';
+import TabItem from '@theme/TabItem';
+import TOCInline from '@theme/TOCInline';
+import SameCategory from '../Categories/_PrimitiveDisposer.mdx';
+
+# ReflectionIT.DisposeGenerator by Fons Sonnemans
+
+
+
+
+## NuGet / site data
+[](https://www.nuget.org/packages/ReflectionIT.DisposeGenerator/)
+[](https://github.com/sonnemaf/ReflectionIT.DisposeGenerator)
+
+
+## Details
+
+### Info
+:::info
+
+Name: **ReflectionIT.DisposeGenerator**
+
+Package Description
+
+Author: Fons Sonnemans
+
+NuGet:
+*https://www.nuget.org/packages/ReflectionIT.DisposeGenerator/*
+
+
+You can find more details at https://github.com/sonnemaf/ReflectionIT.DisposeGenerator
+
+Source: https://github.com/sonnemaf/ReflectionIT.DisposeGenerator
+
+:::
+
+### Author
+:::note
+Fons Sonnemans
+
+:::
+
+## Original Readme
+:::note
+
+### ReflectionIT.DisposeGenerator
+
+A source generator package that implements the dispose and async dispose patterns.
+
+- https://docs.microsoft.com/en-us/dotnet/standard/design-guidelines/dispose-pattern
+- https://docs.microsoft.com/en-us/dotnet/standard/garbage-collection/implementing-dispose
+- https://learn.microsoft.com/en-us/dotnet/standard/garbage-collection/implementing-disposeasync
+
+###### NuGet package
+
+| Package | Version |
+| ------ | ------ |
+| ReflectionIT.DisposeGenerator | [](https://www.nuget.org/packages/ReflectionIT.DisposeGenerator/) |
+
+###### Installation
+
+```xml
+
+```
+
+###### Quick start
+
+Annotate a **partial** class or struct with the `Disposable` attribute and mark disposable fields or properties with `Dispose`.
+
+```cs
+using System;
+using System.IO;
+using ReflectionIT.DisposeGenerator.Attributes;
+
+[Disposable]
+public partial class LogWriter : IDisposable {
+
+ [Dispose]
+ private readonly StreamWriter _streamWriter;
+
+ public LogWriter(string path) => _streamWriter = new StreamWriter(path);
+
+ public void WriteLine(string text) {
+ ThrowIfDisposed();
+ _streamWriter.WriteLine($"{DateTime.Now}\t{text}");
+ }
+}
+```
+
+The generator creates the dispose members for the annotated type, including `_isDisposed`, an `IsDisposed` property, and `ThrowIfDisposed()` by default.
+
+###### Requirements and diagnostics
+
+- The annotated type must be `partial`.
+- `[Disposable]` can be applied to classes and structs.
+- `[Dispose]` and `[AsyncDispose]` can be applied to fields and properties.
+- The generator emits `RITDG001` when a type annotated with `[Disposable]` is not declared `partial`.
+- Members annotated with `[Dispose]` or `[AsyncDispose]` must support the generated dispose call pattern. Otherwise the generated code can produce compiler errors.
+
+######### RITDG001
+
+`RITDG001`: Type `'{typeName}'` is annotated with `[Disposable]` and must be declared partial for ReflectionIT.DisposeGenerator to generate code.
+
+###### Attribute reference
+
+######### `DisposableAttribute`
+
+| Property | Default | Description |
+| --- | --- | --- |
+| `OverrideDispose` | `false` | Generates `Dispose(bool)` as an override instead of generating a public `Dispose()` method. |
+| `OverrideDisposeAsyncCore` | `false` | Generates `DisposeAsyncCore()` as an override instead of generating a public `DisposeAsync()` method. |
+| `GenerateThrowIfDisposed` | `true` | Generates `ThrowIfDisposed()` for guarding public instance members. |
+| `ExplicitInterfaceImplementation` | `false` | Generates explicit `IDisposable.Dispose()` and `IAsyncDisposable.DisposeAsync()` implementations when applicable. |
+| `IsThreadSafe` | `false` | Uses thread-safe disposal state transitions via `Interlocked.CompareExchange`. |
+| `HasUnmanagedResources` | `false` | Adds a finalizer and `ReleaseUnmanagedResources()` partial method support. |
+
+######### `DisposeAttribute`
+
+| Property | Default | Description |
+| --- | --- | --- |
+| `SetToNull` | `false` | Sets the annotated field or property to `null` after disposal. |
+
+######### `AsyncDisposeAttribute`
+
+| Property | Default | Description |
+| --- | --- | --- |
+| `SetToNull` | `false` | Sets the annotated field or property to `null` after asynchronous disposal. |
+| `ConfigureAwait` | `true` | Controls the `ConfigureAwait(...)` value used for generated async disposal calls. |
+
+###### What gets generated
+
+Depending on the options and the annotated members, the generator can create:
+
+- `Dispose()`
+- `Dispose(bool)`
+- `DisposeAsync()`
+- `DisposeAsyncCore()`
+- `IsDisposed`
+- `ThrowIfDisposed()`
+- `_isDisposed`
+- a finalizer
+- `ReleaseUnmanagedResources()`
+
+###### Recommended use of `ThrowIfDisposed`
+
+Call `ThrowIfDisposed()` at the start of public instance members that depend on resources managed by the generated dispose pattern. The generated method uses the generated `IsDisposed` property, so derived types can customize disposed-state checks through `IsDisposed` instead of overriding `ThrowIfDisposed()`.
+
+```cs
+using ReflectionIT.DisposeGenerator.Attributes;
+
+[Disposable]
+public partial class LogWriter : IDisposable {
+
+ [Dispose]
+ private readonly StreamWriter _streamWriter;
+
+ public LogWriter(string path) => _streamWriter = new StreamWriter(path);
+
+ public void WriteLine(string text) {
+ ThrowIfDisposed();
+ _streamWriter.WriteLine($"{DateTime.Now}\t{text}");
+ }
+}
+```
+
+This helps fail fast with an `ObjectDisposedException` when the instance is used after it has been disposed.
+
+###### `SetToNull` usage
+
+Use `SetToNull` when the property or field should be set to `null` after disposal.
+
+```cs
+using ReflectionIT.DisposeGenerator.Attributes;
+
+[Disposable]
+public partial class LogWriter : IDisposable {
+
+ [Dispose(SetToNull = true)]
+ private StreamWriter StreamWriter \{ get; set; }
+
+ public LogWriter(string path) => StreamWriter = new StreamWriter(path);
+
+ public void WriteLine(string text) {
+ ThrowIfDisposed();
+ StreamWriter.WriteLine($"{DateTime.Now}\t{text}");
+ }
+}
+```
+
+This generates the following partial class, which disposes the `StreamWriter` property and sets it to `null`.
+
+```cs
+partial class LogWriter
+{
+ ///
+ /// Releases all resources used by the current instance.
+ ///
+ public void Dispose() {
+ Dispose(disposing: true);
+ global::System.GC.SuppressFinalize(this);
+ }
+
+ ///
+ /// Tracks whether the current instance has been disposed. This field must not be modified manually.
+ ///
+ private bool _isDisposed;
+
+ ///
+ /// Gets a value indicating whether the current instance has been disposed.
+ ///
+ protected virtual bool IsDisposed => _isDisposed;
+
+ ///
+ /// Throws an exception if the current instance has been disposed.
+ ///
+ protected void ThrowIfDisposed() {
+ if (IsDisposed) {
+ throw new global::System.ObjectDisposedException(nameof(LogWriter));
+ }
+ }
+
+ ///
+ /// Releases the unmanaged resources used by the current instance and optionally releases the managed resources.
+ ///
+ /// "true" to release managed resources; otherwise, "false".
+ protected virtual void Dispose(bool disposing) {
+ if (_isDisposed) {
+ return;
+ }
+ _isDisposed = true;
+ if (disposing) {
+ this.StreamWriter?.Dispose();
+ }
+ StreamWriter = null;
+ }
+
+}
+```
+
+###### Async dispose
+
+Use `AsyncDispose` for fields or properties that support `DisposeAsync()`.
+
+```cs
+using System;
+using System.IO;
+using ReflectionIT.DisposeGenerator.Attributes;
+
+[Disposable]
+public partial class LogWriter : IAsyncDisposable {
+
+ [AsyncDispose]
+ private readonly StreamWriter _streamWriter;
+
+ public LogWriter(string path) => _streamWriter = new StreamWriter(path);
+}
+```
+
+This generates `DisposeAsync()` and `DisposeAsyncCore()`. If the same member also has `[Dispose]`, the generator supports both sync and async cleanup patterns.
+
+```cs
+partial class LogWriter
+{
+ ///
+ /// Asynchronously releases all resources used by the current instance.
+ ///
+ ///
+ /// A task that represents the asynchronous dispose operation.
+ ///
+ public async global::System.Threading.Tasks.ValueTask DisposeAsync() {
+ await DisposeAsyncCore().ConfigureAwait(false);
+ global::System.GC.SuppressFinalize(this);
+ }
+
+ ///
+ /// Tracks whether the current instance has been disposed. This field must not be modified manually.
+ ///
+ private bool _isDisposed;
+
+ ///
+ /// Gets a value indicating whether the current instance has been disposed.
+ ///
+ protected virtual bool IsDisposed => _isDisposed;
+
+ ///
+ /// Throws an exception if the current instance has been disposed.
+ ///
+ protected void ThrowIfDisposed() {
+ if (IsDisposed) {
+ throw new global::System.ObjectDisposedException(nameof(LogWriter));
+ }
+ }
+
+ ///
+ /// Asynchronously releases the resources used by the current instance.
+ ///
+ ///
+ /// A task that represents the asynchronous dispose operation.
+ ///
+ protected virtual async global::System.Threading.Tasks.ValueTask DisposeAsyncCore() {
+ if (_isDisposed) {
+ return;
+ }
+ _isDisposed = true;
+ if (this._streamWriter != null) {
+ await this._streamWriter.DisposeAsync().ConfigureAwait(false);
+ }
+ }
+
+}
+```
+
+###### Implement the dispose pattern for a derived class
+
+A class derived from a class that already implements `IDisposable` should not implement `IDisposable` again, because the base implementation of `IDisposable.Dispose` is inherited by derived classes.
+
+Set `OverrideDispose = true` for the derived partial class. In that case, the public parameterless `Dispose()` method is not generated, and the protected `Dispose(bool)` method is generated as an override instead.
+
+```cs
+[Disposable(OverrideDispose = true)]
+public partial class SecondLogWriter : LogWriter {
+
+ [Dispose]
+ private StreamWriter SecondStreamWriter \{ get; }
+
+ public SecondLogWriter(string path) : base(path) => SecondStreamWriter = new StreamWriter(path + "2");
+
+ public override void WriteLine(string text) {
+ base.WriteLine(text);
+ SecondStreamWriter.WriteLine($"{DateTime.Now}\t{text.ToUpper()}");
+ }
+}
+```
+
+This generates the following partial class, which disposes the `SecondStreamWriter` property.
+
+```cs
+partial class SecondLogWriter
+{
+ ///
+ /// Tracks whether the current instance has been disposed. This field must not be modified manually.
+ ///
+ private bool _isDisposed;
+
+ ///
+ /// Gets a value indicating whether the current instance has been disposed.
+ ///
+ protected override bool IsDisposed => _isDisposed || base.IsDisposed;
+
+ ///
+ /// Throws an exception if the current instance has been disposed.
+ ///
+ protected void ThrowIfDisposed() {
+ if (IsDisposed) {
+ throw new global::System.ObjectDisposedException(nameof(SecondLogWriter));
+ }
+ }
+
+ ///
+ /// Releases the unmanaged resources used by the current instance and optionally releases the managed resources.
+ ///
+ /// "true" to release managed resources; otherwise, "false".
+ protected override void Dispose(bool disposing) {
+ if (_isDisposed) {
+ return;
+ }
+ _isDisposed = true;
+ if (disposing) {
+ this.SecondStreamWriter?.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+}
+```
+
+###### Unmanaged resources
+
+Set `HasUnmanagedResources = true` to include unmanaged resource cleanup support.
+Then implement the partial method `ReleaseUnmanagedResources()`, which releases the unmanaged resource.
+
+If you need to work with unmanaged resources, it is strongly recommended to wrap the unmanaged `IntPtr` handle in a [SafeHandle](https://learn.microsoft.com/en-us/dotnet/standard/garbage-collection/implementing-dispose#safe-handles).
+
+```cs
+[Disposable(HasUnmanagedResources = true)]
+public partial class LogWriterWithAnExtraIntPtr : IDisposable {
+
+ private readonly IntPtr _pointer;
+
+ [Dispose]
+ private StreamWriter StreamWriter \{ get; }
+
+ public LogWriterWithAnExtraIntPtr(string path) {
+ StreamWriter = new StreamWriter(path);
+ _pointer = Marshal.AllocHGlobal(cb: 128);
+ }
+
+ public void WriteLine(string text) => StreamWriter.WriteLine($"{DateTime.Now}\t{text}");
+
+ protected virtual partial void ReleaseUnmanagedResources() => Marshal.FreeHGlobal(_pointer);
+}
+```
+
+This generates the following partial class with a finalizer and a partial method named `ReleaseUnmanagedResources()` that you must implement.
+
+```cs
+partial class LogWriterWithAnExtraIntPtr
+{
+ ///
+ /// Releases all resources used by the current instance.
+ ///
+ public void Dispose() {
+ Dispose(disposing: true);
+ global::System.GC.SuppressFinalize(this);
+ }
+
+ ///
+ /// Releases unmanaged resources held by the current instance.
+ ///
+ ~LogWriterWithAnExtraIntPtr() {
+ Dispose(disposing: false);
+ }
+
+ ///
+ /// Releases unmanaged resources held by the current instance.
+ ///
+ protected virtual partial void ReleaseUnmanagedResources();
+
+ ///
+ /// Tracks whether the current instance has been disposed. This field must not be modified manually.
+ ///
+ private bool _isDisposed;
+
+ ///
+ /// Gets a value indicating whether the current instance has been disposed.
+ ///
+ protected virtual bool IsDisposed => _isDisposed;
+
+ ///
+ /// Throws an exception if the current instance has been disposed.
+ ///
+ protected void ThrowIfDisposed() {
+ if (IsDisposed) {
+ throw new global::System.ObjectDisposedException(nameof(LogWriterWithAnExtraIntPtr));
+ }
+ }
+
+ ///
+ /// Releases the unmanaged resources used by the current instance and optionally releases the managed resources.
+ ///
+ /// "true" to release managed resources; otherwise, "false".
+ protected virtual void Dispose(bool disposing) {
+ if (_isDisposed) {
+ return;
+ }
+ _isDisposed = true;
+ if (disposing) {
+ this.StreamWriter?.Dispose();
+ }
+ ReleaseUnmanagedResources();
+ }
+
+}
+```
+
+###### Thread-safe disposal
+
+Use `IsThreadSafe = true` to ensure thread-safe disposal via `Interlocked.CompareExchange`.
+
+```cs
+[Disposable(IsThreadSafe = true)]
+public partial class LogWriter : IDisposable {
+
+ [Dispose]
+ private readonly StreamWriter _streamWriter;
+
+ public LogWriter(string path) => _streamWriter = new StreamWriter(path);
+
+ public void WriteLine(string text) => _streamWriter.WriteLine($"{DateTime.Now}\t{text}");
+}
+```
+
+This generates the following partial class, which uses `Interlocked.CompareExchange` to ensure thread-safe disposal.
+
+```cs
+partial class LogWriter
+{
+ ///
+ /// Releases all resources used by the current instance.
+ ///
+ public void Dispose() {
+ Dispose(disposing: true);
+ global::System.GC.SuppressFinalize(this);
+ }
+
+ ///
+ /// Detects redundant Dispose() calls in a thread-safe manner. _isDisposed == 0 means Dispose(bool) has not been called yet, and _isDisposed == 1 means Dispose(bool) has already been called. This field must not be modified manually.
+ ///
+ private int _isDisposed;
+
+ ///
+ /// Gets a value indicating whether the current instance has been disposed.
+ ///
+ protected virtual bool IsDisposed => _isDisposed != 0;
+
+ ///
+ /// Throws an exception if the current instance has been disposed.
+ ///
+ protected void ThrowIfDisposed() {
+ if (IsDisposed) {
+ throw new global::System.ObjectDisposedException(nameof(LogWriter));
+ }
+ }
+
+ ///
+ /// Releases the unmanaged resources used by the current instance and optionally releases the managed resources.
+ ///
+ /// "true" to release managed resources; otherwise, "false".
+ protected virtual void Dispose(bool disposing) {
+ if (global::System.Threading.Interlocked.CompareExchange(ref _isDisposed, 1, 0) != 0) {
+ return;
+ }
+ if (disposing) {
+ this._streamWriter?.Dispose();
+ }
+ }
+
+}
+```
+
+###### Troubleshooting
+
+######### Why do I get `RITDG001`?
+
+The type marked with `[Disposable]` is not declared `partial`. Add the `partial` keyword to the class or struct declaration.
+
+######### Why do I get compiler errors for `Dispose()` or `DisposeAsync()` on an annotated member?
+
+The generator emits calls to `Dispose()` for `[Dispose]` members and `DisposeAsync()` for `[AsyncDispose]` members. Make sure the annotated member supports the corresponding API.
+
+######### Why was no code generated?
+
+Common reasons:
+
+- the type is not `partial`
+- no fields or properties were annotated with `[Dispose]` or `[AsyncDispose]`
+- the type only has invalid attribute usage that prevents successful compilation
+
+###### License
+
+This project is licensed under the MIT License. See the [LICENSE](https://github.com/sonnemaf/ReflectionIT.DisposeGenerator/LICENSE.md) file for details.
+
+
+:::
+
+### About
+:::note
+
+Automatically implements the IDisposable pattern for classes that contain disposable fields.
+
+
+:::
+
+## How to use
+
+### Example (source csproj, source files)
+
+
+
+
+
+This is the CSharp Project that references **ReflectionIT.DisposeGenerator**
+```xml showLineNumbers {14}
+
+
+
+ Exe
+ net10.0
+ enable
+ enable
+
+
+ true
+ $(BaseIntermediateOutputPath)\GX
+
+
+
+
+
+
+
+```
+
+
+
+
+
+ This is the use of **ReflectionIT.DisposeGenerator** in *Program.cs*
+
+```csharp showLineNumbers
+using IDisposableGeneratorDemo;
+//https://github.com/benutomo-dev/RoslynComponents
+using (var db = new DALDB())
+{
+ Console.WriteLine("before releasing");
+}
+Console.WriteLine("after releasing");
+```
+
+
+
+
+ This is the use of **ReflectionIT.DisposeGenerator** in *ConnectionDB.cs*
+
+```csharp showLineNumbers
+using ReflectionIT.DisposeGenerator.Attributes;
+
+namespace IDisposableGeneratorDemo;
+class ConnectionDB : IDisposable
+{
+ static int count = 0;
+ public ConnectionDB()
+ {
+ Interlocked.Increment(ref count);
+ }
+ public void Dispose()
+ {
+ Console.WriteLine($"disposing connectiondb {Interlocked.Decrement(ref count)}");
+ }
+}
+
+```
+
+
+
+
+### Generated Files
+
+Those are taken from $(BaseIntermediateOutputPath)\GX
+
+
+
+
+```csharp showLineNumbers
+//------------------------------------------------------------------------------
+//
+// This code was generated by the ReflectionIT.DisposeGenerator source generator
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+//------------------------------------------------------------------------------
+#pragma warning disable
+#nullable enable annotations
+
+namespace IDisposableGeneratorDemo
+{
+ partial class DALDB
+ {
+ ///
+ /// Releases all resources used by the current instance.
+ ///
+ [global::System.CodeDom.Compiler.GeneratedCode("ReflectionIT.DisposeGenerator", "0.4.2.0")]
+ [global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage]
+ public void Dispose() {
+ Dispose(disposing: true);
+ global::System.GC.SuppressFinalize(this);
+ }
+
+ ///
+ /// Tracks whether the current instance has been disposed. This field must not be modified manually.
+ ///
+ [global::System.CodeDom.Compiler.GeneratedCode("ReflectionIT.DisposeGenerator", "0.4.2.0")]
+ private bool _isDisposed;
+
+ ///
+ /// Gets a value indicating whether the current instance has been disposed.
+ ///
+ [global::System.CodeDom.Compiler.GeneratedCode("ReflectionIT.DisposeGenerator", "0.4.2.0")]
+ [global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage]
+ protected virtual bool IsDisposed => _isDisposed;
+
+ ///
+ /// Throws an exception if the current instance has been disposed.
+ ///
+ [global::System.CodeDom.Compiler.GeneratedCode("ReflectionIT.DisposeGenerator", "0.4.2.0")]
+ [global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage]
+ protected void ThrowIfDisposed() {
+ if (IsDisposed) {
+ throw new global::System.ObjectDisposedException(nameof(DALDB));
+ }
+ }
+
+ ///
+ /// Releases the unmanaged resources used by the current instance and optionally releases the managed resources.
+ ///
+ /// "true" to release managed resources; otherwise, "false".
+ [global::System.CodeDom.Compiler.GeneratedCode("ReflectionIT.DisposeGenerator", "0.4.2.0")]
+ [global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage]
+ protected virtual void Dispose(bool disposing) {
+ if (_isDisposed) {
+ return;
+ }
+ _isDisposed = true;
+ if (disposing) {
+ this.cn?.Dispose();
+ this.cn1?.Dispose();
+ }
+ }
+
+ }
+}
+
+```
+
+
+
+
+## Useful
+
+### Download Example (.NET C#)
+
+:::tip
+
+[Download Example project ReflectionIT.DisposeGenerator ](/sources/ReflectionIT.DisposeGenerator.zip)
+
+:::
+
+
+### Share ReflectionIT.DisposeGenerator
+
+
+
+https://ignatandrei.github.io/RSCG_Examples/v2/docs/ReflectionIT.DisposeGenerator
+
+
+
diff --git a/v2/rscg_examples_site/docs/RSCG-Examples/index.md b/v2/rscg_examples_site/docs/RSCG-Examples/index.md
index 8c8bb8058..b4b863083 100644
--- a/v2/rscg_examples_site/docs/RSCG-Examples/index.md
+++ b/v2/rscg_examples_site/docs/RSCG-Examples/index.md
@@ -1,7 +1,7 @@
---
sidebar_position: 30
-title: 278 RSCG list by category
-description: 278 RSCG list by category
+title: 279 RSCG list by category
+description: 279 RSCG list by category
slug: /rscg-examples
---
@@ -509,7 +509,7 @@ import DocCardList from '@theme/DocCardList';
## Disposer
- Expand Disposer =>examples:7
+ Expand Disposer =>examples:8
@@ -545,6 +545,11 @@ import DocCardList from '@theme/DocCardList';
[Dirge](/docs/Dirge)
+
+
+
+[ReflectionIT.DisposeGenerator](/docs/ReflectionIT.DisposeGenerator)
+
@@ -1903,6 +1908,8 @@ flowchart LR;
Disposer--> Dirge((Dirge))
+ Disposer--> ReflectionIT.DisposeGenerator((ReflectionIT.DisposeGenerator))
+
Documentation--> REslava.ResultFlow((REslava.ResultFlow))
EnhancementClass--> System.Text.RegularExpressions((System.Text.RegularExpressions))
diff --git a/v2/rscg_examples_site/docs/about.md b/v2/rscg_examples_site/docs/about.md
index 105ed1587..1e2688e03 100644
--- a/v2/rscg_examples_site/docs/about.md
+++ b/v2/rscg_examples_site/docs/about.md
@@ -6,7 +6,7 @@ title: About
## Content
You will find here code examples
-of 278 Roslyn Source Code Generator (RSCG)
+of 279 Roslyn Source Code Generator (RSCG)
that can be useful for you. That means, you will write more elegant and concise code - even if the generators code is not always nice to look.
## Are those examples ready for production?
diff --git a/v2/rscg_examples_site/docs/indexRSCG.md b/v2/rscg_examples_site/docs/indexRSCG.md
index 973078e5b..bebbc18da 100644
--- a/v2/rscg_examples_site/docs/indexRSCG.md
+++ b/v2/rscg_examples_site/docs/indexRSCG.md
@@ -7,9 +7,9 @@ slug: /List-of-RSCG
import useBaseUrl from '@docusaurus/useBaseUrl';
-## 278 RSCG with examples in descending chronological order
+## 279 RSCG with examples in descending chronological order
-This is the list of 278 ( 16 from Microsoft) RSCG with examples
+This is the list of 279 ( 16 from Microsoft) RSCG with examples
[See by category](/docs/rscg-examples) [See as json](/exports/RSCG.json) [See as Excel](/exports/RSCG.xlsx)
@@ -20,6 +20,7 @@ This is the list of 278 ( 16 from Microsoft) RSCG with examples
| No | Name | Date | Category |
| --------- | ----- | ---- | -------- |
+|279| [ReflectionIT.DisposeGenerator by Fons Sonnemans ](/docs/ReflectionIT.DisposeGenerator)|2026-08-19 => 19 August 2026 | [Disposer](/docs/Categories/Disposer) |
|278| [Atulin.AutoDbSet by Angius Atulin ](/docs/Atulin.AutoDbSet)|2026-08-18 => 18 August 2026 | [EntityFramework](/docs/Categories/EntityFramework) |
|277| [Bennewitz.Ninja.AutoVersioning by Brian Bennewitz ](/docs/Bennewitz.Ninja.AutoVersioning)|2026-07-04 => 04 July 2026 | [EnhancementProject](/docs/Categories/EnhancementProject) |
|276| [TinyBDD.MSTest by Jerrett Davis ](/docs/TinyBDD.MSTest)|2026-07-03 => 03 July 2026 | [Tests](/docs/Categories/Tests) |
diff --git a/v2/rscg_examples_site/src/components/HomepageFeatures/index.js b/v2/rscg_examples_site/src/components/HomepageFeatures/index.js
index 8052e4ba6..b693194eb 100644
--- a/v2/rscg_examples_site/src/components/HomepageFeatures/index.js
+++ b/v2/rscg_examples_site/src/components/HomepageFeatures/index.js
@@ -4,7 +4,7 @@ import styles from './styles.module.css';
const FeatureList = [
{
-title: '278 Examples (16 from MSFT)',
+title: '279 Examples (16 from MSFT)',
Svg: require('@site/static/img/undraw_docusaurus_mountain.svg').default,
description: (
<>
diff --git a/v2/rscg_examples_site/static/exports/RSCG.json b/v2/rscg_examples_site/static/exports/RSCG.json
index fbc42e3d5..1f4eda312 100644
--- a/v2/rscg_examples_site/static/exports/RSCG.json
+++ b/v2/rscg_examples_site/static/exports/RSCG.json
@@ -2225,6 +2225,14 @@
"Source": "https://github.com/Atulin/AutoDbSet",
"Category": "EntityFramework",
"AddedOn": "2026-08-18T00:00:00"
+ },
+ {
+ "Name": "ReflectionIT.DisposeGenerator",
+ "Link": "https://ignatandrei.github.io/RSCG_Examples/v2/docs/ReflectionIT.DisposeGenerator",
+ "NuGet": "https://www.nuget.org/packages/ReflectionIT.DisposeGenerator/",
+ "Source": "https://github.com/sonnemaf/ReflectionIT.DisposeGenerator",
+ "Category": "Disposer",
+ "AddedOn": "2026-08-19T00:00:00"
}
]
}
\ No newline at end of file
diff --git a/v2/rscg_examples_site/static/exports/RSCG.xlsx b/v2/rscg_examples_site/static/exports/RSCG.xlsx
index 57bad84aa..e33512de2 100644
Binary files a/v2/rscg_examples_site/static/exports/RSCG.xlsx and b/v2/rscg_examples_site/static/exports/RSCG.xlsx differ
diff --git a/v2/rscg_examples_site/static/sources/ReflectionIT.DisposeGenerator.zip b/v2/rscg_examples_site/static/sources/ReflectionIT.DisposeGenerator.zip
new file mode 100644
index 000000000..0bef01031
Binary files /dev/null and b/v2/rscg_examples_site/static/sources/ReflectionIT.DisposeGenerator.zip differ