This example shows the Build-Up pattern in dependency injection, where an existing object is injected with necessary dependencies through its properties, methods, or fields.
using Shouldly;
using Pure.DI;
DI.Setup(nameof(Composition))
.RootArg<string>("name")
.Bind().To(Guid.NewGuid)
.Bind().To(ctx => {
var person = new Person();
// Injects dependencies into an existing object
ctx.BuildUp(person);
return person;
})
.Bind().To<Greeter>()
// Composition root
.Root<IGreeter>("GetGreeter");
var composition = new Composition();
var greeter = composition.GetGreeter("Nik");
greeter.Person.Name.ShouldBe("Nik");
greeter.Person.Id.ShouldNotBe(Guid.Empty);
interface IPerson
{
string Name { get; }
Guid Id { get; }
}
class Person : IPerson
{
// The Dependency attribute specifies to perform an injection and its order
[Dependency] public string Name { get; set; } = "";
public Guid Id { get; private set; } = Guid.Empty;
// The Dependency attribute specifies to perform an injection and its order
[Dependency] public void SetId(Guid id) => Id = id;
}
interface IGreeter
{
IPerson Person { get; }
}
record Greeter(IPerson Person) : IGreeter;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 runKey Concepts: Build-Up - injecting dependencies into an already created object Dependency Attribute - marker for identifying injectable members
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 IGreeter GetGreeter(string name)
{
if (name is null) throw new ArgumentNullException(nameof(name));
Person transientPerson268;
var localPerson = new Person();
// Injects dependencies into an existing object
Guid transientGuid270 = Guid.NewGuid();
localPerson.Name = name;
localPerson.SetId(transientGuid270);
transientPerson268 = localPerson;
return new Greeter(transientPerson268);
}
}Class diagram:
---
config:
maxTextSize: 2147483647
maxEdges: 2147483647
class:
hideEmptyMembersBox: true
---
classDiagram
Guid --|> IComparable
Guid --|> IComparableᐸGuidᐳ
Guid --|> IEquatableᐸGuidᐳ
Guid --|> IFormattable
Guid --|> IParsableᐸGuidᐳ
Guid --|> ISpanFormattable
Guid --|> ISpanParsableᐸGuidᐳ
Guid --|> IUtf8SpanFormattable
Guid --|> IUtf8SpanParsableᐸGuidᐳ
Person --|> IPerson
Greeter --|> IGreeter
Greeter --|> IEquatableᐸGreeterᐳ
Composition ..> Greeter : IGreeter GetGreeter(string name)
Person o-- String : Argument "name"
Person *-- Guid : Guid
Greeter *-- Person : IPerson
namespace Pure.DI.UsageTests.Basics.BuildUpScenario {
class Composition {
<<partial>>
+IGreeter GetGreeter(string name)
}
class Greeter {
<<record>>
+Greeter(IPerson Person)
}
class IGreeter {
<<interface>>
}
class IPerson {
<<interface>>
}
class Person {
<<class>>
+String Name
+SetId(Guid id) : Void
}
}
namespace System {
class Guid {
<<struct>>
}
class IComparable {
<<interface>>
}
class IComparableᐸGuidᐳ {
<<interface>>
}
class IEquatableᐸGreeterᐳ {
<<interface>>
}
class IEquatableᐸGuidᐳ {
<<interface>>
}
class IFormattable {
<<interface>>
}
class IParsableᐸGuidᐳ {
<<interface>>
}
class ISpanFormattable {
<<interface>>
}
class ISpanParsableᐸGuidᐳ {
<<interface>>
}
class IUtf8SpanFormattable {
<<interface>>
}
class IUtf8SpanParsableᐸGuidᐳ {
<<interface>>
}
class String {
<<class>>
}
}