Skip to content

Latest commit

 

History

History
163 lines (138 loc) · 4.09 KB

File metadata and controls

163 lines (138 loc) · 4.09 KB

Dependent compositions

The Setup method has an additional argument kind, which defines the type of composition:

  • CompositionKind.Public - will create a normal composition class, this is the default setting and can be omitted, it can also use the DependsOn method to use it as a dependency in other compositions
  • CompositionKind.Internal - the composition class will not be created, but that composition can be used to create other compositions by calling the DependsOn method with its name
  • CompositionKind.Global - the composition class will also not be created, but that composition will automatically be used to create other compositions Use dependent compositions to split large object graphs into reusable setup layers.
using Pure.DI;
using static Pure.DI.CompositionKind;

// This setup does not generate code, but can be used as a dependency
// and requires the use of the "DependsOn" call to add it as a dependency
DI.Setup("Infrastructure", Internal)
    .Bind<IDatabase>().To<SqlDatabase>();

// This setup generates code and can also be used as a dependency
DI.Setup(nameof(Composition))
    // Uses "Infrastructure" setup
    .DependsOn("Infrastructure")
    .Bind<IUserService>().To<UserService>()
    .Root<IUserService>("UserService");

// As in the previous case, this setup generates code and can also be used as a dependency
DI.Setup(nameof(OtherComposition))
    // Uses "Composition" setup
    .DependsOn(nameof(Composition))
    .Root<Ui>("Ui");

var composition = new Composition();
var userService = composition.UserService;

var otherComposition = new OtherComposition();
userService = otherComposition.Ui.UserService;

interface IDatabase;

class SqlDatabase : IDatabase;

interface IUserService;

class UserService(IDatabase database) : IUserService;

partial class Ui(IUserService userService)
{
    public IUserService UserService { get; } = userService;
}
Running this code sample locally
dotnet --list-sdk
  • Create a net10.0 (or later) console application
dotnet new console -n Sample
  • Add a reference to the NuGet package
dotnet add package Pure.DI
  • Copy the example code into the Program.cs file

You are ready to run the example 🚀

dotnet run

Limitations: too many setup layers can make graph ownership unclear; keep boundaries explicit and naming consistent. See also: Composition roots, Global compositions.

The following partial class will be generated:

partial class Composition
{
  public IUserService UserService
  {
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    get
    {
      return new UserService(new SqlDatabase());
    }
  }
}

The following partial class will be generated:

partial class OtherComposition
{
  public IUserService UserService
  {
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    get
    {
      return new UserService(new SqlDatabase());
    }
  }

  public Ui Ui
  {
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    get
    {
      return new Ui(new UserService(new SqlDatabase()));
    }
  }
}

Class diagram:

---
 config:
  maxTextSize: 2147483647
  maxEdges: 2147483647
  class:
   hideEmptyMembersBox: true
---
classDiagram
	UserService --|> IUserService
	SqlDatabase --|> IDatabase
	OtherComposition ..> Ui : Ui Ui
	OtherComposition ..> UserService : IUserService UserService
	UserService *--  SqlDatabase : IDatabase
	Ui *--  UserService : IUserService
	namespace Pure.DI.UsageTests.Advanced.DependentCompositionsScenario {
		class IDatabase {
			<<interface>>
		}
		class IUserService {
			<<interface>>
		}
		class OtherComposition {
		<<partial>>
		+Ui Ui
		+IUserService UserService
		}
		class SqlDatabase {
				<<class>>
			+SqlDatabase()
		}
		class Ui {
				<<class>>
			+Ui(IUserService userService)
		}
		class UserService {
				<<class>>
			+UserService(IDatabase database)
		}
	}
Loading