Skip to content

Latest commit

 

History

History
193 lines (162 loc) · 4.79 KB

File metadata and controls

193 lines (162 loc) · 4.79 KB

Tracking disposable instances per a composition root

Demonstrates how disposable instances are tracked per composition root and disposed when the composition is disposed.

using Shouldly;
using Pure.DI;

var composition = new Composition();
var orderProcessingService1 = composition.OrderProcessingService;
var orderProcessingService2 = composition.OrderProcessingService;

orderProcessingService2.Dispose();

// Checks that the disposable instances
// associated with orderProcessingService2 have been disposed of
orderProcessingService2.Value.DbConnection.IsDisposed.ShouldBeTrue();

// Checks that the disposable instances
// associated with orderProcessingService1 have not been disposed of
orderProcessingService1.Value.DbConnection.IsDisposed.ShouldBeFalse();

orderProcessingService1.Dispose();

// Checks that the disposable instances
// associated with orderProcessingService1 have been disposed of
orderProcessingService1.Value.DbConnection.IsDisposed.ShouldBeTrue();

interface IDbConnection
{
    bool IsDisposed { get; }
}

class DbConnection : IDbConnection, IDisposable
{
    public bool IsDisposed { get; private set; }

    public void Dispose() => IsDisposed = true;
}

interface IOrderProcessingService
{
    public IDbConnection DbConnection { get; }
}

class OrderProcessingService(IDbConnection dbConnection) : IOrderProcessingService
{
    public IDbConnection DbConnection { get; } = dbConnection;
}

partial class Composition
{
    static void Setup() =>

        DI.Setup()
            .Bind().To<DbConnection>()
            .Bind().To<OrderProcessingService>()

            // A special composition root
            // that allows to manage disposable dependencies
            .Root<Owned<IOrderProcessingService>>("OrderProcessingService");
}
Running this code sample locally
dotnet --list-sdk
  • Create a net10.0 (or later) console application
dotnet new console -n Sample
dotnet add package Pure.DI
dotnet add package Shouldly
  • Copy the example code into the Program.cs file

You are ready to run the example 🚀

dotnet run

Note

Disposable tracking ensures proper cleanup of all disposable instances within a composition scope.

The following partial class will be generated:

partial class Composition
{
#if NET9_0_OR_GREATER
  private readonly Lock _lock = new Lock();
#else
  private readonly Object _lock = new Object();
#endif

  public Owned<IOrderProcessingService> OrderProcessingService
  {
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    get
    {
      var perBlockOwned167 = new Owned();
      Owned<IOrderProcessingService> perBlockOwned166;
      // Creates the owner of an instance
      Owned transientOwned168;
      Owned localOwned7 = perBlockOwned167;
      transientOwned168 = localOwned7;
      lock (_lock)
      {
        perBlockOwned167.Add(transientOwned168);
      }

      IOwned localOwned6 = transientOwned168;
      var transientDbConnection170 = new DbConnection();
      lock (_lock)
      {
        perBlockOwned167.Add(transientDbConnection170);
      }

      IOrderProcessingService localValue10 = new OrderProcessingService(transientDbConnection170);
      perBlockOwned166 = new Owned<IOrderProcessingService>(localValue10, localOwned6);
      lock (_lock)
      {
        perBlockOwned167.Add(perBlockOwned166);
      }

      return perBlockOwned166;
    }
  }
}

Class diagram:

---
 config:
  maxTextSize: 2147483647
  maxEdges: 2147483647
  class:
   hideEmptyMembersBox: true
---
classDiagram
	Owned --|> IOwned
	DbConnection --|> IDbConnection
	OrderProcessingService --|> IOrderProcessingService
	Composition ..> OwnedᐸIOrderProcessingServiceᐳ : OwnedᐸIOrderProcessingServiceᐳ OrderProcessingService
	OrderProcessingService *--  DbConnection : IDbConnection
	OwnedᐸIOrderProcessingServiceᐳ *--  Owned : IOwned
	OwnedᐸIOrderProcessingServiceᐳ *--  OrderProcessingService : IOrderProcessingService
	namespace Pure.DI {
		class IOwned {
			<<interface>>
		}
		class Owned {
				<<class>>
		}
		class OwnedᐸIOrderProcessingServiceᐳ {
				<<struct>>
		}
	}
	namespace Pure.DI.UsageTests.Advanced.TrackingDisposableScenario {
		class Composition {
		<<partial>>
		+OwnedᐸIOrderProcessingServiceᐳ OrderProcessingService
		}
		class DbConnection {
				<<class>>
			+DbConnection()
		}
		class IDbConnection {
			<<interface>>
		}
		class IOrderProcessingService {
			<<interface>>
		}
		class OrderProcessingService {
				<<class>>
			+OrderProcessingService(IDbConnection dbConnection)
		}
	}
Loading