Skip to content

Latest commit

 

History

History
151 lines (124 loc) · 3.25 KB

required-properties-or-fields.md

File metadata and controls

151 lines (124 loc) · 3.25 KB

Required properties or fields

This example demonstrates 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>("name")
    .Bind<IDependency>().To<Dependency>()
    .Bind<IService>().To<Service>()

    // Composition root
    .Root<IService>("Root");

var composition = new Composition(name: "My Service");
var service = composition.Root;
service.Dependency.ShouldBeOfType<Dependency>();
service.Name.ShouldBe("My Service");

interface IDependency;

class Dependency : IDependency;

interface IService
{
    string Name { get; }

    IDependency Dependency { get; }
}

class Service : IService
{
    public required string ServiceNameField;

    public string Name => ServiceNameField;

    // The required property will be injected automatically
    // without additional effort
    public required IDependency Dependency { get; init; }
}
Running this code sample locally
dotnet --list-sdk
  • Create a net9.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

This 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
{
  private readonly Composition _root;

  private readonly string _argName;

  [OrdinalAttribute(128)]
  public Composition(string name)
  {
    _argName = name ?? throw new ArgumentNullException(nameof(name));
    _root = this;
  }

  internal Composition(Composition parentScope)
  {
    _root = (parentScope ?? throw new ArgumentNullException(nameof(parentScope)))._root;
    _argName = _root._argName;
  }

  public IService Root
  {
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    get
    {
      return new Service()
      {
        ServiceNameField = _argName,
        Dependency = new Dependency()
      };
    }
  }
}

Class diagram:

---
 config:
  class:
   hideEmptyMembersBox: true
---
classDiagram
	Dependency --|> IDependency
	Service --|> IService
	Composition ..> Service : IService Root
	Service o-- String : Argument "name"
	Service *--  Dependency : IDependency
	namespace Pure.DI.UsageTests.Basics.RequiredPropertiesOrFieldsScenario {
		class Composition {
		<<partial>>
		+IService Root
		}
		class Dependency {
			+Dependency()
		}
		class IDependency {
			<<interface>>
		}
		class IService {
			<<interface>>
		}
		class Service {
			+Service()
			+String ServiceNameField
			+IDependency Dependency
		}
	}
	namespace System {
		class String {
		}
	}
Loading