This example shows how to use default values in dependency injection when explicit injection is not possible.
using Shouldly;
using Pure.DI;
DI.Setup(nameof(Composition))
.Bind<ISensor>().To<MotionSensor>()
.Bind<ISecuritySystem>().To<SecuritySystem>()
// Composition root
.Root<ISecuritySystem>("SecuritySystem");
var composition = new Composition();
var securitySystem = composition.SecuritySystem;
securitySystem.Sensor.ShouldBeOfType<MotionSensor>();
securitySystem.SystemName.ShouldBe("Home Guard");
interface ISensor;
class MotionSensor : ISensor;
interface ISecuritySystem
{
string SystemName { get; }
ISensor Sensor { get; }
}
// If injection cannot be performed explicitly,
// the default value will be used
class SecuritySystem(string systemName = "Home Guard") : ISecuritySystem
{
public string SystemName { get; } = systemName;
// The 'required' modifier ensures that the property is set during initialization.
// The default value 'new MotionSensor()' provides a fallback
// if no dependency is injected.
public required ISensor Sensor { get; init; } = new MotionSensor();
}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 Sampledotnet 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 runThe key points are:
- Default constructor arguments can be used for simple values
- The DI will use these defaults if no explicit bindings are provided
This example shows how to handle default values in a dependency injection scenario:
- Constructor Default Argument: The
SecuritySystemclass has a constructor with a default value for the name parameter. If no value is provided, "Home Guard" will be used. - Required Property with Default: The
Sensorproperty is marked as required but has a default instantiation. This ensures that:- The property must be set
- If no explicit injection occurs, a default value will be used
The following partial class will be generated:
partial class Composition
{
public ISecuritySystem SecuritySystem
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get
{
return new SecuritySystem("Home Guard")
{
Sensor = new MotionSensor()
};
}
}
}Class diagram:
---
config:
maxTextSize: 2147483647
maxEdges: 2147483647
class:
hideEmptyMembersBox: true
---
classDiagram
MotionSensor --|> ISensor
SecuritySystem --|> ISecuritySystem
Composition ..> SecuritySystem : ISecuritySystem SecuritySystem
SecuritySystem *-- MotionSensor : ISensor
SecuritySystem *-- String : String
namespace Pure.DI.UsageTests.Basics.DefaultValuesScenario {
class Composition {
<<partial>>
+ISecuritySystem SecuritySystem
}
class ISecuritySystem {
<<interface>>
}
class ISensor {
<<interface>>
}
class MotionSensor {
<<class>>
+MotionSensor()
}
class SecuritySystem {
<<class>>
+SecuritySystem(String systemName)
+ISensor Sensor
}
}
namespace System {
class String {
<<class>>
}
}