Skip to content

Latest commit

 

History

History
189 lines (159 loc) · 5.14 KB

File metadata and controls

189 lines (159 loc) · 5.14 KB

Default lifetime for a type

For example, if a certain lifetime is used more often than others, you can make it the default lifetime for a certain type:

using Shouldly;
using Pure.DI;
using static Pure.DI.Lifetime;

DI.Setup(nameof(Composition))
    // In a real base station, the time source (PTP/GNSS disciplined clock)
    // is a shared infrastructure component:
    // it should be created once per station and reused everywhere.
    .DefaultLifetime<ITimeSource>(Singleton)

    // Time source used by multiple subsystems
    .Bind().To<GnssTimeSource>()

    // Upper-level station components (usually transient by default)
    .Bind().To<BaseStationController>()
    .Bind().To<RadioScheduler>()

    // Composition root (represents "get me a controller instance")
    .Root<IBaseStationController>("Controller");

var composition = new Composition();

// Two independent controller instances (e.g., two independent operations)
var controller1 = composition.Controller;
var controller2 = composition.Controller;

controller1.ShouldNotBe(controller2);

// Inside one controller we request ITimeSource twice:
// the same singleton instance should be injected both times.
controller1.SyncTimeSource.ShouldBe(controller1.SchedulerTimeSource);

// Across different controllers the same station-wide time source is reused.
controller1.SyncTimeSource.ShouldBe(controller2.SyncTimeSource);

// A shared station-wide dependency
interface ITimeSource
{
    long UnixTimeMilliseconds { get; }
}

// Represents a GNSS-disciplined clock (or PTP grandmaster input).
// In real deployments you'd talk to a driver / NIC / daemon here.
class GnssTimeSource : ITimeSource
{
    public long UnixTimeMilliseconds => DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
}

interface IBaseStationController
{
    ITimeSource SyncTimeSource { get; }
    ITimeSource SchedulerTimeSource { get; }
}

// A "top-level" controller of the base station.
// It depends on the time source for synchronization and for scheduling decisions.
class BaseStationController(
    ITimeSource syncTimeSource,
    RadioScheduler scheduler)
    : IBaseStationController
{
    // Used for time synchronization / frame timing
    public ITimeSource SyncTimeSource { get; } = syncTimeSource;

    // Demonstrates that scheduler also uses the same singleton time source
    public ITimeSource SchedulerTimeSource { get; } = scheduler.TimeSource;
}

// A subsystem (e.g., MAC scheduler) that also needs precise time.
class RadioScheduler(ITimeSource timeSource)
{
    public ITimeSource TimeSource { get; } = timeSource;
}
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

Setting default lifetime for types simplifies configuration when the same lifetime is consistently applied.

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

  private GnssTimeSource? _singletonGnssTimeSource62;

  public IBaseStationController Controller
  {
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    get
    {
      EnsureGnssTimeSourceExists();
      return new BaseStationController(_singletonGnssTimeSource62, new RadioScheduler(_singletonGnssTimeSource62));
      [MethodImpl(MethodImplOptions.AggressiveInlining)]
      void EnsureGnssTimeSourceExists()
      {
        if (_singletonGnssTimeSource62 is null)
          lock (_lock)
            if (_singletonGnssTimeSource62 is null)
            {
              _singletonGnssTimeSource62 = new GnssTimeSource();
            }
      }
    }
  }
}

Class diagram:

---
 config:
  maxTextSize: 2147483647
  maxEdges: 2147483647
  class:
   hideEmptyMembersBox: true
---
classDiagram
	GnssTimeSource --|> ITimeSource
	BaseStationController --|> IBaseStationController
	Composition ..> BaseStationController : IBaseStationController Controller
	BaseStationController o-- "Singleton" GnssTimeSource : ITimeSource
	BaseStationController *--  RadioScheduler : RadioScheduler
	RadioScheduler o-- "Singleton" GnssTimeSource : ITimeSource
	namespace Pure.DI.UsageTests.Lifetimes.DefaultLifetimeForTypeScenario {
		class BaseStationController {
				<<class>>
			+BaseStationController(ITimeSource syncTimeSource, RadioScheduler scheduler)
		}
		class Composition {
		<<partial>>
		+IBaseStationController Controller
		}
		class GnssTimeSource {
				<<class>>
			+GnssTimeSource()
		}
		class IBaseStationController {
			<<interface>>
		}
		class ITimeSource {
			<<interface>>
		}
		class RadioScheduler {
				<<class>>
			+RadioScheduler(ITimeSource timeSource)
		}
	}
Loading