Skip to content

Latest commit

 

History

History
162 lines (135 loc) · 3.76 KB

File metadata and controls

162 lines (135 loc) · 3.76 KB

Required properties or fields

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
dotnet --list-sdk
  • Create a net10.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
{
#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>>
		}
	}
Loading