Implement the dispose pattern using SourceGenerator.
Use this like below.
using IDisposableSourceGenerator;
[IDisposableGenerator]
partial class Foo { } // must be partial class
Then the boilerplate code for the disposable pattern will be generated.
partial class Foo : System.IDisposable
{
protected readonly SimpleCompositeDisposable _disposables =
new SimpleCompositeDisposable();
private bool _disposedValue;
protected virtual void Dispose(bool disposing)
{
if (_disposedValue) return;
if (disposing)
{
// TODO: called on disposing the managed objects.
//OnDisposing();
// TODO: dispose managed state (managed objects).
_disposables.Dispose();
}
// TODO: free unmanaged resources (unmanaged objects) and override a finalizer below.
//DisposeUnmanagedObjects();
// TODO: set large fields to null.
//SetLargeFieldsToNull();
_disposedValue = true;
}
//~Foo() => Dispose(disposing: false);
public void Dispose()
{
Dispose(disposing: true);
System.GC.SuppressFinalize(this);
}
}
Generator declare a _disposables
field of SimpleCompositeDisposable
type . You can add disposable objects with it.
The field name _disposables
can be changed with a generator argument. see CompositeDisposableFieldName.
[IDisposableGenerator]
partial class Foo {
public Foo(IDisposable d) {
_disposables.Add(d); // d will be automatically disposed.
}
}
You can specify the type of CompositeDisposable
.
If you don't specified or set default, the default class IDisposableSourceGenerator.SimpleCompositeDisposable
in the source generator is used.
[IDisposableGenerator(typeof(System.Reactive.Disposables.CompositeDisposable))]
partial class Foo {
public Foo(IDisposable d) {
_disposables.Add(d); // GetType() == typeof(System.Reactive.Disposables.CompositeDisposable)
}
}
You can change the name of CompositeDisposable
field.
If filed name is default or whitespace, it named _disposables
.
using IDisposableSourceGenerator;
[IDisposableGenerator(default, "myAwesomeDisposables")] // CompositeDisposable type is default.
partial class Foo {
public Foo(IDisposable d) {
myAwesomeDisposables.Add(d); // The name specified in the argument.
}
}
Generator generates the IDisposableGeneratorOptions
that has bit flags of which method to implement.
[Flags]
internal enum IDisposableGeneratorOptions {
None = 0x0000,
DisposeUnmanagedObjectsMethod = 0x0001,
SetLargeFieldsToNullMethod = 0x0002,
OnDisposingMethod = 0x0004,
}
Of course, each option can be set simultaneously.
[IDisposableGenerator(default, default, IDisposableGeneratorOptions.DisposeUnmanagedObjectsMethod | IDisposableGeneratorOptions.SetLargeFieldsToNullMethod | IDisposableGeneratorOptions.OnDisposingMethod)]
partial class Foo {
...
}
If you want to release some unmanaged objects, you can use the IDisposableGeneratorOptions.DisposeUnmanagedObjectsMethod
flag.
This option enables the DisposeUnmanagedObjects
method and Finalizer. It will be called from the Dispose
method or Finalizer.
[IDisposableGenerator(default, default, IDisposableGeneratorOptions.DisposeUnmanagedObjectsMethod)]
partial class Foo {
protected virtual partial void DisposeUnmanagedObjects()
{
// release some unmanaged objects in this.
}
}
If you want to set some large fields to null, you can use the IDisposableGeneratorOptions.SetLargeFieldsToNullMethod
flag.
This option enables the SetLargeFieldsToNull
method and Finalizer. It will be called from the Dispose
method or Finalizer.
[IDisposableGenerator(default, default, IDisposableGeneratorOptions.SetLargeFieldsToNullMethod)]
partial class Foo {
protected virtual partial void SetLargeFieldsToNull()
{
// set some large fields to null in this.
}
}
If you want to do something when disposing the managed objects, you can use the IDisposableGeneratorOptions.OnDisposing
flag.
This option enables the OnDisposing
method. It will be called before disposed CompositeDisposables
from the Dispose
method.
[IDisposableGenerator(default, default, IDisposableGeneratorOptions.OnDisposingMethod)]
partial class Foo {
protected virtual partial void OnDisposing()
{
// do something when disposing
}
}
Maybe WPF app requires editing the *.csproj
file.
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>net5.0-windows</TargetFramework>
<UseWPF>true</UseWPF>
<!-- for WPF, add the following settings -->
<IncludePackageReferencesDuringMarkupCompilation>true</IncludePackageReferencesDuringMarkupCompilation>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="IDisposableSourceGenerator" Version="1.0.0" >
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
</ItemGroup>
</Project>
This library is under the MIT License.
本プロジェクトでは以下を参考にさせて頂きました。素晴らしいソフトウェアを公開してくださり感謝いたします。