roots.md

July 5, 2026 ยท View on GitHub

Roots

Sometimes you need roots for all types inherited from available at compile time at the point where the method is called.

using Shouldly;
using Pure.DI;

DI.Setup(nameof(Composition))
    .Bind().As(Lifetime.Singleton).To<Preferences>()
    // Roots can be used to register all descendants of a type as roots.
    .Roots<IWindow>("{type}");

var composition = new Composition();
composition.MainWindow.ShouldBeOfType<MainWindow>();
composition.SettingsWindow.ShouldBeOfType<SettingsWindow>();

interface IPreferences;

class Preferences : IPreferences;

interface IWindow;

class MainWindow(IPreferences preferences) : IWindow;

class SettingsWindow(IPreferences preferences) : IWindow;
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

This feature is useful for plugin-style architectures where you need to expose all implementations of a base type or interface.

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 Preferences? _singletonCompositionInOtherProject;

  public SettingsWindow SettingsWindow
  {
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    get
    {
      if (_singletonCompositionInOtherProject is null)
        lock (_lock)
          if (_singletonCompositionInOtherProject is null)
          {
            _singletonCompositionInOtherProject = new Preferences();
          }

      return new SettingsWindow(_singletonCompositionInOtherProject);
    }
  }

  public MainWindow MainWindow
  {
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    get
    {
      if (_singletonCompositionInOtherProject is null)
        lock (_lock)
          if (_singletonCompositionInOtherProject is null)
          {
            _singletonCompositionInOtherProject = new Preferences();
          }

      return new MainWindow(_singletonCompositionInOtherProject);
    }
  }
}

Class diagram:

---
 config:
  class:
   hideEmptyMembersBox: true
---
classDiagram
	Preferences --|> IPreferences
	Composition ..> SettingsWindow : SettingsWindow SettingsWindow
	Composition ..> MainWindow : MainWindow MainWindow
	SettingsWindow o-- "Singleton" Preferences : IPreferences
	MainWindow o-- "Singleton" Preferences : IPreferences
	namespace Pure.DI.UsageTests.Basics.RootsScenario {
		class Composition {
		<<partial>>
		+MainWindow MainWindow
		+SettingsWindow SettingsWindow
		}
		class IPreferences {
			<<interface>>
		}
		class MainWindow {
				<<class>>
			+MainWindow(IPreferences preferences)
		}
		class Preferences {
				<<class>>
			+Preferences()
		}
		class SettingsWindow {
				<<class>>
			+SettingsWindow(IPreferences preferences)
		}
	}

See also: