This example shows how the required modifier can be used to automatically inject dependencies into properties and fields. When a property or field is marked with required, the DI will automatically inject the dependency without additional effort.
using Shouldly;
using Pure.DI;
DI.Setup(nameof(Composition))
.Arg<string>("connectionString")
.Bind<IDatabase>().To<SqlDatabase>()
.Bind<IUserRepository>().To<UserRepository>()
// Composition root
.Root<IUserRepository>("Repository");
var composition = new Composition(connectionString: "Server=.;Database=MyDb;");
var repository = composition.Repository;
repository.Database.ShouldBeOfType<SqlDatabase>();
repository.ConnectionString.ShouldBe("Server=.;Database=MyDb;");
interface IDatabase;
class SqlDatabase : IDatabase;
interface IUserRepository
{
string ConnectionString { get; }
IDatabase Database { get; }
}
class UserRepository : IUserRepository
{
// The required field will be injected automatically.
// In this case, it gets the value from the composition argument
// of type 'string'.
public required string ConnectionStringField;
public string ConnectionString => ConnectionStringField;
// The required property will be injected automatically
// without additional effort.
public required IDatabase Database { get; init; }
}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 runThis approach simplifies dependency injection by eliminating the need to manually configure bindings for required dependencies, making the code more concise and easier to maintain.
The following partial class will be generated:
partial class Composition
{
#if NET9_0_OR_GREATER
private readonly Lock _lock;
#else
private readonly Object _lock;
#endif
private readonly string _argConnectionString;
[OrdinalAttribute(128)]
public Composition(string connectionString)
{
_argConnectionString = connectionString ?? throw new ArgumentNullException(nameof(connectionString));
#if NET9_0_OR_GREATER
_lock = new Lock();
#else
_lock = new Object();
#endif
}
public IUserRepository Repository
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get
{
return new UserRepository()
{
ConnectionStringField = _argConnectionString,
Database = new SqlDatabase()
};
}
}
}Class diagram:
---
config:
maxTextSize: 2147483647
maxEdges: 2147483647
class:
hideEmptyMembersBox: true
---
classDiagram
SqlDatabase --|> IDatabase
UserRepository --|> IUserRepository
Composition ..> UserRepository : IUserRepository Repository
UserRepository o-- String : Argument "connectionString"
UserRepository *-- SqlDatabase : IDatabase
namespace Pure.DI.UsageTests.Basics.RequiredPropertiesOrFieldsScenario {
class Composition {
<<partial>>
+IUserRepository Repository
}
class IDatabase {
<<interface>>
}
class IUserRepository {
<<interface>>
}
class SqlDatabase {
<<class>>
+SqlDatabase()
}
class UserRepository {
<<class>>
+UserRepository()
+String ConnectionStringField
+IDatabase Database
}
}
namespace System {
class String {
<<class>>
}
}