This scenario shows how to pass an explicit setup context as a root argument. When this occurs: you need external state from the base setup but cannot use a constructor (e.g., Unity MonoBehaviour). What it solves: keeps the dependent composition safe while avoiding constructor arguments. How it is solved in the example: uses DependsOn(..., SetupContextKind.RootArgument, name) and passes the base setup instance to the root method.
using Pure.DI;
using static Pure.DI.CompositionKind;
var baseContext = new BaseComposition { Settings = new AppSettings("staging", 2) };
var composition = new Composition();
var service = composition.Service(baseContext: baseContext);
interface IService
{
string Report { get; }
}
class Service(IAppSettings settings) : IService
{
public string Report { get; } = $"env={settings.Environment}, retries={settings.RetryCount}";
}
internal partial class BaseComposition
{
internal AppSettings Settings { get; set; } = new("", 0);
private void Setup()
{
DI.Setup(nameof(BaseComposition), Internal)
.Bind<IAppSettings>().To(_ => Settings);
}
}
internal partial class Composition
{
private void Setup()
{
// Resolve = Off
DI.Setup(nameof(Composition))
.DependsOn(nameof(BaseComposition), SetupContextKind.RootArgument, "baseContext")
.Bind<IService>().To<Service>()
.Root<IService>("Service");
}
}
record AppSettings(string Environment, int RetryCount) : IAppSettings;
interface IAppSettings
{
string Environment { get; }
int RetryCount { get; }
}Running this code sample locally
- Make sure you have the .NET SDK 10.0 or later installed
dotnet --list-sdk- Create a net10.0 (or later) console application
dotnet new console -n Sample- Add a reference to the NuGet package
dotnet add package Pure.DI- Copy the example code into the Program.cs file
You are ready to run the example 🚀
dotnet runWhat it shows:
- Passing setup context into a root method.
Important points:
- The composition itself can still be created with a parameterless constructor.
Useful when:
- The host (like Unity) creates the composition instance.
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
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public IService Service(BaseComposition baseContext)
{
if (baseContext is null) throw new ArgumentNullException(nameof(baseContext));
AppSettings transientAppSettings34;
BaseComposition localBaseContext = baseContext;
transientAppSettings34 = localBaseContext.Settings;
return new Service(transientAppSettings34);
}
}Class diagram:
---
config:
maxTextSize: 2147483647
maxEdges: 2147483647
class:
hideEmptyMembersBox: true
---
classDiagram
AppSettings --|> IAppSettings
Service --|> IService
Composition ..> Service : IService Service(Pure.DI.UsageTests.Advanced.DependentCompositionsWithRootArgumentScenario.BaseComposition baseContext)
AppSettings o-- BaseComposition : Argument "baseContext"
Service *-- AppSettings : IAppSettings
namespace Pure.DI.UsageTests.Advanced.DependentCompositionsWithRootArgumentScenario {
class AppSettings {
<<record>>
}
class BaseComposition {
<<class>>
}
class Composition {
<<partial>>
+IService Service(Pure.DI.UsageTests.Advanced.DependentCompositionsWithRootArgumentScenario.BaseComposition baseContext)
}
class IAppSettings {
<<interface>>
}
class IService {
<<interface>>
}
class Service {
<<class>>
+Service(IAppSettings settings)
}
}