Skip to content

DevTeam/Pure.DI

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

Pure DI for .NET

NuGet License GitHub Build

Pure.DI is a compile-time dependency injection (DI) code generator. Supports .NET starting with .NET Framework 2.0, released 2005-10-27, and all newer versions.

Usage Requirements

  • .NET SDK 6.0.4+
    Required for compilation. Projects can target older frameworks (e.g., .NET Framework 2.0).
  • C# 8+
    Only required for projects using the Pure.DI source generator. Other projects support any C# version.

Key Features

βœ”οΈ Zero Overhead

Pure.DI is a .NET code generator designed to produce clean, efficient dependency injection logic. By leveraging basic language constructs, it generates straightforward code indistinguishable from manual implementationβ€”essentially composing objects through nested constructor invocations. Unlike traditional DI frameworks, Pure.DI avoids reflection and dynamic instantiation entirely, eliminating performance penalties associated with runtime overhead.

βœ”οΈ Compile-Time Validation

All analysis of object, constructor, and method graphs occurs at compile time. Pure.DI proactively detects and alerts developers to issues such as missing dependencies, cyclic references, or dependencies unsuitable for injectionβ€”ensuring these errors are resolved before execution. This approach guarantees that developers cannot produce a program vulnerable to runtime crashes caused by faulty dependency wiring. The validation process operates seamlessly alongside code development, creating an immediate feedback loop: as you modify your code, Pure.DI verifies its integrity in real time, effectively delivering tested, production-ready logic the moment changes are implemented.

βœ”οΈ Works everywhere

The pure dependency injection approach introduces no runtime dependencies and avoids .NET reflection , ensuring consistent execution across all supported platforms. This includes the Full .NET Framework 2.0+, .NET Core, .NET 5+, UWP/Xbox, .NET IoT, Unity, Xamarin, Native AOT, and beyond. By decoupling runtime constraints, it preserves predictable behavior regardless of the target environment.

βœ”οΈ Familiar Syntax

The Pure.DI API is intentionally designed to closely mirror the APIs of mainstream IoC/DI frameworks. This approach ensures developers can leverage their existing knowledge of dependency injection patterns without requiring significant adaptation to a proprietary syntax.

βœ”οΈ Precise Generics

Pure.DI recommends utilizing dedicated marker types rather than relying on open generics. This approach enables more precise construction of object graphs while allowing developers to fully leverage the capabilities of generic types.

βœ”οΈ Transparency

Pure.DI allows to view and debug the generated code, making debugging and testing easier.

βœ”οΈ Built-in BCL Support

Pure.DI provides native support for numerous Base Class Library (BCL) types out of the box without any extra effort.

When to Use Pure.DI

βœ”οΈ High-Performance Applications

Pure.DI is designed for high-performance applications where speed and minimal memory consumption are critical.

βœ”οΈ Projects with a Focus on Clean Code

Pure.DI is suitable for projects where code cleanliness and minimalism are important factors.

βœ”οΈ Applications with Complex Dependencies

Pure.DI can handle complex dependencies and provides flexible configuration options.

βœ”οΈ Ideal for Libraries

Its high performance, zero memory consumption/preparation overhead, and lack of dependencies make it ideal for building libraries and frameworks.

NuGet packages

NuGet package Description
Pure.DI DI source code generator
Pure.DI.Abstractions Abstractions for Pure.DI
Pure.DI.Templates Template package, for creating projects from the shell/command line
Pure.DI.MS Add-ons on Pure.DI to work with Microsoft DI

SchrΓΆdinger's cat will demonstrate how it all works CSharp

The reality is

Cat

Let's create an abstraction

interface IBox<out T>
{
    T Content { get; }
}

interface ICat
{
    State State { get; }
}

enum State { Alive, Dead }

Here's our implementation

record CardboardBox<T>(T Content): IBox<T>;

class ShroedingersCat(Lazy<State> superposition): ICat
{
    // The decoherence of the superposition
    // at the time of observation via an irreversible process
    public State State => superposition.Value;
}

Important

Our abstraction and implementation knows nothing about the magic of DI or any frameworks.

Let's glue it all together

Add the Pure.DI package to your project:

NuGet

Let's bind the abstractions to their implementations and set up the creation of the object graph:

DI.Setup(nameof(Composition))
    // Models a random subatomic event that may or may not occur
    .Bind().As(Singleton).To<Random>()
    // Quantum superposition of two states: Alive or Dead
    .Bind().To((Random random) => (State)random.Next(2))
    .Bind().To<ShroedingersCat>()
    // Cardboard box with any contents
    .Bind().To<CardboardBox<TT>>()
    // Composition Root
    .Root<Program>("Root");

Note

In fact, the Bind().As(Singleton).To<Random>() binding is unnecessary since Pure.DI supports many .NET BCL types out of the box, including Random. It was added just for the example of using the Singleton lifetime.

The above code specifies the generation of a partial class named Composition, this name is defined in the DI.Setup(nameof(Composition)) call. This class contains a Root property that returns a graph of objects with an object of type Program as the root. The type and name of the property is defined by calling Root<Program>("Root"). The code of the generated class looks as follows:

partial class Composition
{
    private readonly Lock _lock = new Lock();
    private Random? _random;
    
    public Program Root
    {
      get
      {
        var stateFunc = new Func<State>(() => {
              if (_random is null)
                lock (_lock)
                  if (_random is null)
                    _random = new Random();

              return (State)_random.Next(2)
            });

        return new Program(
          new CardboardBox<ICat>(
            new ShroedingersCat(
              new Lazy<State>(
                stateFunc))));    
      }
    }

    public T Resolve<T>() { ... }
    public T Resolve<T>(object? tag) { ... }

    public object Resolve(Type type) { ... }
    public object Resolve(Type type, object? tag)) { ... }
}
Class diagram
classDiagram
    ShroedingersCat --|> ICat
    CardboardBoxᐸICatᐳ --|> IBoxᐸICatᐳ
    CardboardBoxᐸICatᐳ --|> IEquatableᐸCardboardBoxᐸICatᐳᐳ
    Composition ..> Program : Program Root
    State o-- "Singleton" Random : Random
    ShroedingersCat *--  LazyᐸStateᐳ : LazyᐸStateᐳ
    Program *--  CardboardBoxᐸICatᐳ : IBoxᐸICatᐳ
    CardboardBoxᐸICatᐳ *--  ShroedingersCat : ICat
    LazyᐸStateᐳ o-- "PerBlock" FuncᐸStateᐳ : FuncᐸStateᐳ
    FuncᐸStateᐳ *--  State : State
    
namespace Sample {
    class CardboardBoxᐸICatᐳ {
        <<record>>
        +CardboardBox(ICat Content)
    }
    
    class Composition {
        <<partial>>
        +Program Root
        + T ResolveᐸTᐳ()
        + T ResolveᐸTᐳ(object? tag)
        + object Resolve(Type type)
        + object Resolve(Type type, object? tag)
    }
    
    class IBoxᐸICatᐳ {
        <<interface>>
    }
    
    class ICat {
        <<interface>>
    }
    
    class Program {
        <<class>>
        +Program(IBoxᐸICatᐳ box)
    }
    
    class ShroedingersCat {
    <<class>>
        +ShroedingersCat(LazyᐸStateᐳ superposition)
    }
    
    class State {
        <<enum>>
    }
}
    
namespace System {
    class FuncᐸStateᐳ {
        <<delegate>>
    }
    
    class IEquatableᐸCardboardBoxᐸICatᐳᐳ {
        <<interface>>
    }
    
    class LazyᐸStateᐳ {
        <<class>>
    }
    
    class Random {
        <<class>>
        +Random()
    }
}
Loading

You can see the class diagram at any time by following the link in the comment of the generated class:

Obviously, this code does not depend on other libraries, does not use type reflection or any other tricks that can negatively affect performance and memory consumption. It looks like an efficient code written by hand. At any given time, you can study it and understand how it works.

The public Program Root { get; } property here is a Composition Root, the only place in the application where the composition of the object graph for the application takes place. Each instance is created by only basic language constructs, which compiles with all optimizations with minimal impact on performance and memory consumption. In general, applications may have multiple composition roots and thus such properties. Each composition root must have its own unique name, which is defined when the Root<T>(string name) method is called, as shown in the above code.

Time to open boxes!

class Program(IBox<ICat> box)
{
  // Composition Root, a single place in an application
  // where the composition of the object graphs
  // for an application take place
  static void Main() => new Composition().Root.Run();

  private void Run() => Console.WriteLine(box);
}

Pure.DI creates efficient code in a pure DI paradigm, using only basic language constructs as if you were writing code by hand. This allows you to take full advantage of Dependency Injection everywhere and always, without any compromise!

The full analog of this application with top-level statements can be found here.

Just try creating a project from scratch!

Install the projects template

dotnet new install Pure.DI.Templates

In some directory, create a console application

dotnet new di

And run it

dotnet run

API

Pure.DI
BindAttribute

Indicates that a property or method can be automatically added as a binding.

internal class DependencyProvider
            {
                [Bind()]
                public Dependency Dep => new Dependency();
            }
            
internal class DependencyProvider
            {
                [Bind(typeof(IDependency<TT>), Lifetime.Singleton)]
                public Dependency GetDep<T>() => new Dependency();
            }
            
internal class DependencyProvider
            {
                [Bind(typeof(IDependency), Lifetime.PerResolve, "some tag")]
                public Dependency GetDep(int id) => new Dependency(id);
            }
            

See also Exposed.

Constructor BindAttribute(System.Type,Pure.DI.Lifetime,System.Object[])

Creates an attribute instance.

Buckets`1

For internal use.

CannotResolveException

Represents an exception thrown when a required composition root cannot be resolved.

Constructor CannotResolveException(System.String,System.Type,System.Object)

Initializes a new instance of the CannotResolveException class with a specified error message, type, and optional tag describing the resolution failure.

  • parameter message - A user-friendly message that describes the error that occurred during the resolution process. The message should be clear and informative, providing enough context to understand the nature of the failure.

  • parameter type - The Type used to resolve a composition root.

  • parameter tag - The tag used to resolve a composition root.

Constructor CannotResolveException(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext)

Initializes a new instance of the CannotResolveException class with serialized data.

  • parameter info - The object that holds the serialized object data.

  • parameter context - The contextual information about the source or destination.

Property Type

Gets the type used to resolve a composition root.

Property Tag

Gets the tag used to resolve a composition root.

CompositionKind

Determines how the partial class will be generated. The Setup(System.String,Pure.DI.CompositionKind) method has an additional argument kind , which defines the type of composition:

DI.Setup("BaseComposition", CompositionKind.Internal);
            

See also Setup(System.String,Pure.DI.CompositionKind).

Field Public

This value is used by default. If this value is specified, a normal partial class will be generated.

Field Internal

If this value is specified, the class will not be generated, but this setting can be used by other users as a baseline. The API call DependsOn(System.String[]) is mandatory.

Field Global

No partial classes will be created when this value is specified, but this setting is the baseline for all installations in the current project, and the API call DependsOn(System.String[]) is not required.

DependencyAttribute

Combines injection tagging and ordering capabilities in a single attribute. Allows simultaneous specification of both tag and ordinal for dependency injection points.

  • parameter tag - Identifies the specific dependency variation to inject. See also Tags(System.Object[]).

  • parameter ordinal - Determines injection order priority (lower values execute first).

See also OrdinalAttribute.

See also TagAttribute.

Constructor DependencyAttribute(System.Object,System.Int32)

Initializes an attribute instance with optional tag and priority.

  • parameter tag - Identifies a specific dependency variation. See also Tags(System.Object[]).

  • parameter ordinal - Injection execution priority (0 = highest priority). Default: 0.

DI

An API for a Dependency Injection setup.

See also Setup(System.String,Pure.DI.CompositionKind).

Method Setup(System.String,Pure.DI.CompositionKind)

Begins the definitions of the Dependency Injection setup chain.

interface IDependency;
            
             
             class Dependency: IDependency;
            
             
             interface IService;
            
             
             class Service(IDependency dependency): IService;
            
             
             DI.Setup("Composition")
               .Bind<IDependency>().To<Dependency>()
               .Bind<IService>().To<Service>()
               .Root<IService>("Root");
             
  • parameter compositionTypeName - An optional argument specifying the partial class name to generate.

  • parameter kind - An optional argument specifying the kind of setup. Please CompositionKind for details. It defaults to Public .

  • returns Reference to the setup continuation chain.

GenericTypeArgumentAttribute

Represents a generic type argument attribute. It allows you to create custom generic type argument such as TTS, TTDictionary`2, etc.

[GenericTypeArgument]
            internal interface TTMy: IMy { }
            

See also GenericTypeArgumentAttribute``1.

See also GenericTypeArgument``1.

Hint

Provides configuration hints for fine-tuning code generation behavior.

// Resolve = Off
            DI.Setup("Composition")
                .Bind<IDependency>().To<Dependency>();
            
        or using the API call _Hint(Pure.DI.Hint,System.String)_:
DI.Setup("Composition")
                .Hint(Hint.Resolve, "Off")
                .Bind<IDependency>().To<Dependency>();
            

See also Hint(Pure.DI.Hint,System.String).

Field Resolve

Enables/disables generation of Resolve methods. Default: On .

// Resolve = Off
             DI.Setup("Composition")
                 .Bind<IDependency>().To<Dependency>();
             
         or using the API call _Hint(Pure.DI.Hint,System.String)_:
DI.Setup("Composition")
                 .Hint(Hint.Resolve, "Off")
                 .Bind<IDependency>().To<Dependency>();
             
Field OnNewInstance

Enables/disables generation of OnNewInstance hooks. Default: Off .

// OnNewInstance = On
             DI.Setup("Composition")
                 .Bind<IDependency>().To<Dependency>();
             
         or using the API call _Hint(Pure.DI.Hint,System.String)_:
DI.Setup("Composition")
                 .Hint(Hint.OnNewInstance, "On")
                 .Bind<IDependency>().To<Dependency>();
             
Field OnNewInstancePartial

Enables/disables partial method generation for OnNewInstance. Default: On .

// OnNewInstancePartial = On
             DI.Setup("Composition")
                 .Bind<IDependency>().To<Dependency>();
             
         or using the API call _Hint(Pure.DI.Hint,System.String)_:
DI.Setup("Composition")
                 .Hint(Hint.OnNewInstancePartial, "On")
                 .Bind<IDependency>().To<Dependency>();
             
Field OnNewInstanceImplementationTypeNameRegularExpression

Regex filter for instance types in OnNewInstance hooks. Default: .+ .

// OnNewInstanceImplementationTypeNameRegularExpression = Dependency
             DI.Setup("Composition")
                 .Bind<IDependency>().To<Dependency>();
             
         or using the API call _Hint(Pure.DI.Hint,System.String)_:
DI.Setup("Composition")
                 .Hint(Hint.OnNewInstanceImplementationTypeNameRegularExpression, "Dependency")
                 .Bind<IDependency>().To<Dependency>();
             
Field OnNewInstanceImplementationTypeNameWildcard

Wildcard filter for instance types in OnNewInstance hooks. Default: * .

// OnNewInstanceImplementationTypeNameWildcard = *Dependency
             DI.Setup("Composition")
                 .Bind<IDependency>().To<Dependency>();
             
         or using the API call _Hint(Pure.DI.Hint,System.String)_:
DI.Setup("Composition")
                 .Hint(OnNewInstanceImplementationTypeNameWildcard, "*Dependency")
                 .Bind<IDependency>().To<Dependency>();
             
Field OnNewInstanceTagRegularExpression

Regex filter for tags in OnNewInstance hooks. Default: .+ .

// OnNewInstanceTagRegularExpression = IDependency
             DI.Setup("Composition")
                 .Bind<IDependency>().To<Dependency>();
             
         or using the API call _Hint(Pure.DI.Hint,System.String)_:
DI.Setup("Composition")
                 .Hint(Hint.OnNewInstanceTagRegularExpression, "IDependency")
                 .Bind<IDependency>().To<Dependency>();
             
Field OnNewInstanceTagWildcard

Wildcard filter for tags in OnNewInstance hooks. Default: * .

// OnNewInstanceTagWildcard = *IDependency
             DI.Setup("Composition")
                 .Bind<IDependency>().To<Dependency>();
             
         or using the API call _Hint(Pure.DI.Hint,System.String)_:
DI.Setup("Composition")
                 .Hint(Hint.OnNewInstanceTagWildcard, "*IDependency")
                 .Bind<IDependency>().To<Dependency>();
             
Field OnNewInstanceLifetimeRegularExpression

Regex filter for lifetimes in OnNewInstance hooks. Default: .+ .

// OnNewInstanceLifetimeRegularExpression = Singleton
             DI.Setup("Composition")
                 .Bind<IDependency>().To<Dependency>();
             
         or using the API call _Hint(Pure.DI.Hint,System.String)_:
DI.Setup("Composition")
                 .Hint(Hint.OnNewInstanceLifetimeRegularExpression, "Singleton")
                 .Bind<IDependency>().To<Dependency>();
             
Field OnNewInstanceLifetimeWildcard

Wildcard filter for lifetimes in OnNewInstance hooks. Default: * .

// OnNewInstanceLifetimeWildcard = *Singleton
             DI.Setup("Composition")
                 .Bind<IDependency>().To<Dependency>();
             
         or using the API call _Hint(Pure.DI.Hint,System.String)_:
DI.Setup("Composition")
                 .Hint(Hint.OnNewInstanceLifetimeWildcard, "*Singleton")
                 .Bind<IDependency>().To<Dependency>();
             
Field OnDependencyInjection

Enables/disables dependency injection interception hooks. Default: Off .

// OnDependencyInjection = On
             DI.Setup("Composition")
                 .Bind<IDependency>().To<Dependency>();
             
         or using the API call _Hint(Pure.DI.Hint,System.String)_:
DI.Setup("Composition")
                 .Hint(Hint.OnDependencyInjection, "On")
                 .Bind<IDependency>().To<Dependency>();
             
Field OnDependencyInjectionPartial

Enables/disables partial method generation for dependency injection hooks. Default: On .

// OnDependencyInjectionPartial = On
             DI.Setup("Composition")
                 .Bind<IDependency>().To<Dependency>();
             
         or using the API call _Hint(Pure.DI.Hint,System.String)_:
DI.Setup("Composition")
                 .Hint(Hint.OnDependencyInjectionPartial, "On")
                 .Bind<IDependency>().To<Dependency>();
             
Field OnDependencyInjectionImplementationTypeNameRegularExpression

Regex filter for implementation types in dependency injection hooks. Default: .+ .

// OnDependencyInjectionImplementationTypeNameRegularExpression = Dependency
             DI.Setup("Composition")
                 .Bind<IDependency>().To<Dependency>();
             
         or using the API call _Hint(Pure.DI.Hint,System.String)_:
DI.Setup("Composition")
                 .Hint(Hint.OnDependencyInjectionImplementationTypeNameRegularExpression, "Dependency")
                 .Bind<IDependency>().To<Dependency>();
             
Field OnDependencyInjectionImplementationTypeNameWildcard

Wildcard filter for implementation types in dependency injection hooks. Default: * .

// OnDependencyInjectionImplementationTypeNameWildcard = *Dependency
             DI.Setup("Composition")
                 .Bind<IDependency>().To<Dependency>();
             
         or using the API call _Hint(Pure.DI.Hint,System.String)_:
DI.Setup("Composition")
                 .Hint(Hint.OnDependencyInjectionImplementationTypeNameWildcard, "*Dependency")
                 .Bind<IDependency>().To<Dependency>();
             
Field OnDependencyInjectionContractTypeNameRegularExpression

Regex filter for contract types in dependency injection hooks. Default: .+ .

// OnDependencyInjectionContractTypeNameRegularExpression = IDependency
             DI.Setup("Composition")
                 .Bind<IDependency>().To<Dependency>();
             
         or using the API call _Hint(Pure.DI.Hint,System.String)_:
DI.Setup("Composition")
                 .Hint(Hint.OnDependencyInjectionContractTypeNameRegularExpression, "IDependency")
                 .Bind<IDependency>().To<Dependency>();
             
Field OnDependencyInjectionContractTypeNameWildcard

Wildcard filter for contract types in dependency injection hooks. Default: * .

// OnDependencyInjectionContractTypeNameWildcard = *IDependency
             DI.Setup("Composition")
                 .Bind<IDependency>().To<Dependency>();
             
         or using the API call _Hint(Pure.DI.Hint,System.String)_:
DI.Setup("Composition")
                 .Hint(Hint.OnDependencyInjectionContractTypeNameWildcard, "*IDependency")
                 .Bind<IDependency>().To<Dependency>();
             
Field OnDependencyInjectionTagRegularExpression

Regex filter for tags in dependency injection hooks. Default: .+ .

// OnDependencyInjectionTagRegularExpression = MyTag
             DI.Setup("Composition")
                 .Bind<IDependency>("MyTag").To<Dependency>();
             
         or using the API call _Hint(Pure.DI.Hint,System.String)_:
DI.Setup("Composition")
                 .Hint(Hint.OnDependencyInjectionTagRegularExpression, "MyTag")
                 .Bind<IDependency>("MyTag").To<Dependency>();
             
Field OnDependencyInjectionTagWildcard

Wildcard filter for tags in dependency injection hooks. Default: * .

// OnDependencyInjectionTagWildcard = MyTag
             DI.Setup("Composition")
                 .Bind<IDependency>("MyTag").To<Dependency>();
             
         or using the API call _Hint(Pure.DI.Hint,System.String)_:
DI.Setup("Composition")
                 .Hint(Hint.OnDependencyInjectionTagWildcard, "MyTag")
                 .Bind<IDependency>("MyTag").To<Dependency>();
             
Field OnDependencyInjectionLifetimeRegularExpression

Regex filter for lifetimes in dependency injection hooks. Default: .+ .

// OnDependencyInjectionLifetimeRegularExpression = Singleton
             DI.Setup("Composition")
                 .Bind<IDependency>().To<Dependency>();
             
         or using the API call _Hint(Pure.DI.Hint,System.String)_:
DI.Setup("Composition")
                 .Hint(Hint.OnDependencyInjectionLifetimeRegularExpression, "Singleton")
                 .Bind<IDependency>().To<Dependency>();
             
Field OnDependencyInjectionLifetimeWildcard

Wildcard filter for lifetimes in dependency injection hooks. Default: * .

// OnDependencyInjectionLifetimeWildcard = *Singleton
             DI.Setup("Composition")
                 .Bind<IDependency>().To<Dependency>();
             
         or using the API call _Hint(Pure.DI.Hint,System.String)_:
DI.Setup("Composition")
                 .Hint(Hint.OnDependencyInjectionLifetimeWildcard, "*Singleton")
                 .Bind<IDependency>().To<Dependency>();
             
Field OnCannotResolve

Enables/disables unresolved dependency handlers. Default: Off .

// OnCannotResolve = On
             DI.Setup("Composition")
                 .Bind<IDependency>().To<Dependency>();
             
         or using the API call _Hint(Pure.DI.Hint,System.String)_:
DI.Setup("Composition")
                 .Hint(Hint.OnCannotResolve, "On")
                 .Bind<IDependency>().To<Dependency>();
             
Field OnCannotResolvePartial

Enables/disables partial method generation for unresolved dependency handlers. Default: On .

// OnCannotResolvePartial = On
             DI.Setup("Composition")
                 .Bind<IDependency>().To<Dependency>();
             
         or using the API call _Hint(Pure.DI.Hint,System.String)_:
DI.Setup("Composition")
                 .Hint(Hint.OnCannotResolvePartial, "On")
                 .Bind<IDependency>().To<Dependency>();
             
Field OnCannotResolveContractTypeNameRegularExpression

Regex filter for contract types in unresolved dependency handlers. Default: .+ .

// OnCannotResolveContractTypeNameRegularExpression = OtherType
             DI.Setup("Composition")
                 .Bind<IDependency>().To<Dependency>();
             
         or using the API call _Hint(Pure.DI.Hint,System.String)_:
DI.Setup("Composition")
                 .Hint(Hint.OnCannotResolveContractTypeNameRegularExpression, "OtherType")
                 .Bind<IDependency>().To<Dependency>();
             
Field OnCannotResolveContractTypeNameWildcard

Wildcard filter for contract types in unresolved dependency handlers. Default: * .

// OnCannotResolveContractTypeNameWildcard = *OtherType
             DI.Setup("Composition")
                 .Bind<IDependency>().To<Dependency>();
             
         or using the API call _Hint(Pure.DI.Hint,System.String)_:
DI.Setup("Composition")
                 .Hint(Hint.OnCannotResolveContractTypeNameWildcard, "*OtherType")
                 .Bind<IDependency>().To<Dependency>();
             
Field OnCannotResolveTagRegularExpression

Regex filter for tags in unresolved dependency handlers. Default: .+ .

// OnCannotResolveTagRegularExpression = MyTag
             DI.Setup("Composition")
                 .Bind<IDependency>().To<Dependency>();
             
         or using the API call _Hint(Pure.DI.Hint,System.String)_:
DI.Setup("Composition")
                 .Hint(Hint.OnCannotResolveTagRegularExpression, "MyTag")
                 .Bind<IDependency>().To<Dependency>();
             
Field OnCannotResolveTagWildcard

Wildcard filter for tags in unresolved dependency handlers. Default: * .

// OnCannotResolveTagWildcard = MyTag
             DI.Setup("Composition")
                 .Bind<IDependency>().To<Dependency>();
             
         or using the API call _Hint(Pure.DI.Hint,System.String)_:
DI.Setup("Composition")
                 .Hint(Hint.OnCannotResolveTagWildcard, "MyTag")
                 .Bind<IDependency>().To<Dependency>();
             
Field OnCannotResolveLifetimeRegularExpression

Regex filter for lifetimes in unresolved dependency handlers. Default: .+ .

// OnCannotResolveLifetimeRegularExpression = Singleton
             DI.Setup("Composition")
                 .Bind<IDependency>().To<Dependency>();
             
         or using the API call _Hint(Pure.DI.Hint,System.String)_:
DI.Setup("Composition")
                 .Hint(Hint.OnCannotResolveLifetimeRegularExpression, "Singleton")
                 .Bind<IDependency>().To<Dependency>();
             
Field OnCannotResolveLifetimeWildcard

Wildcard filter for lifetimes in unresolved dependency handlers. Default: * .

// OnCannotResolveLifetimeWildcard = *Singleton
             DI.Setup("Composition")
                 .Bind<IDependency>().To<Dependency>();
             
         or using the API call _Hint(Pure.DI.Hint,System.String)_:
DI.Setup("Composition")
                 .Hint(Hint.OnCannotResolveLifetimeWildcard, "*Singleton")
                 .Bind<IDependency>().To<Dependency>();
             
Field OnNewRoot

Enables/disables composition root registration event handlers. Default: Off .

// OnNewRoot = On
             DI.Setup("Composition")
                 .Bind<IDependency>().To<Dependency>();
             
         or using the API call _Hint(Pure.DI.Hint,System.String)_:
DI.Setup("Composition")
                 .Hint(Hint.OnNewRoot, "On")
                 .Bind<IDependency>().To<Dependency>();
             
Field OnNewRootPartial

Enables/disables partial method generation for composition root events. Default: Off .

// OnNewRootPartial = On
             DI.Setup("Composition")
                 .Bind<IDependency>().To<Dependency>();
             
         or using the API call _Hint(Pure.DI.Hint,System.String)_:
DI.Setup("Composition")
                 .Hint(Hint.OnNewRootPartial, "On")
                 .Bind<IDependency>().To<Dependency>();
             
Field ToString

Enables/disables generation of mermaid-format class diagram via ToString(). Default: Off .

// ToString = On
             DI.Setup("Composition")
                 .Bind<IDependency>().To<Dependency>();
             
         or using the API call _Hint(Pure.DI.Hint,System.String)_:
DI.Setup("Composition")
                 .Hint(Hint.ToString, "On")
                 .Bind<IDependency>().To<Dependency>();
             
Field ThreadSafe

Enables/disables thread-safe composition object creation. Default: On .

// ThreadSafe = Off
             DI.Setup("Composition")
                 .Bind<IDependency>().To<Dependency>();
             
         or using the API call _Hint(Pure.DI.Hint,System.String)_:
DI.Setup("Composition")
                 .Hint(Hint.ThreadSafe, "Off")
                 .Bind<IDependency>().To<Dependency>();
             
Field ResolveMethodModifiers

Modifier override for Resolve() method. Default: public .

// ResolveMethodModifiers = internal
             DI.Setup("Composition")
                 .Bind<IDependency>().To<Dependency>();
             
         or using the API call _Hint(Pure.DI.Hint,System.String)_:
DI.Setup("Composition")
                 .Hint(Hint.ResolveMethodModifiers, "internal")
                 .Bind<IDependency>().To<Dependency>();
             
Field ResolveMethodName

Name override for Resolve() method. Default: Resolve .

// ResolveMethodName = GetService
             DI.Setup("Composition")
                 .Bind<IDependency>().To<Dependency>();
             
         or using the API call _Hint(Pure.DI.Hint,System.String)_:
DI.Setup("Composition")
                 .Hint(Hint.ResolveMethodName, "GetService")
                 .Bind<IDependency>().To<Dependency>();
             
Field ResolveByTagMethodModifiers

Modifier override for Resolve(tag) method. Default: public .

// ResolveByTagMethodModifiers = internal
             DI.Setup("Composition")
                 .Bind<IDependency>().To<Dependency>();
             
         or using the API call _Hint(Pure.DI.Hint,System.String)_:
DI.Setup("Composition")
                 .Hint(Hint.ResolveByTagMethodModifiers, "internal")
                 .Bind<IDependency>().To<Dependency>();
             
Field ResolveByTagMethodName

Name override for Resolve(tag) method. Default: Resolve . For example

// ResolveByTagMethodName = GetService
             DI.Setup("Composition")
                 .Bind<IDependency>().To<Dependency>();
             
         or using the API call _Hint(Pure.DI.Hint,System.String)_:
DI.Setup("Composition")
                 .Hint(Hint.ResolveByTagMethodName, "GetService")
                 .Bind<IDependency>().To<Dependency>();
             
Field ObjectResolveMethodModifiers

Modifier override for Resolve(Type) method. Default: public .

// ObjectResolveMethodModifiers = internal
             DI.Setup("Composition")
                 .Bind<IDependency>().To<Dependency>();
             
         or using the API call _Hint(Pure.DI.Hint,System.String)_:
DI.Setup("Composition")
                 .Hint(Hint.ObjectResolveMethodModifiers, "internal")
                 .Bind<IDependency>().To<Dependency>();
             
Field ObjectResolveMethodName

Name override for Resolve(Type) method. Default: Resolve .

// ObjectResolveMethodName = GetService
             DI.Setup("Composition")
                 .Bind<IDependency>().To<Dependency>();
             
         or using the API call _Hint(Pure.DI.Hint,System.String)_:
DI.Setup("Composition")
                 .Hint(Hint.ObjectResolveMethodName, "GetService")
                 .Bind<IDependency>().To<Dependency>();
             
Field ObjectResolveByTagMethodModifiers

Modifier override for Resolve(Type, tag) method. Default: public .

// ObjectResolveByTagMethodModifiers = internal
             DI.Setup("Composition")
                 .Bind<IDependency>().To<Dependency>();
             
         or using the API call _Hint(Pure.DI.Hint,System.String)_:
DI.Setup("Composition")
                 .Hint(Hint.ObjectResolveByTagMethodModifiers, "internal")
                 .Bind<IDependency>().To<Dependency>();
             
Field ObjectResolveByTagMethodName

Name override for Resolve(Type, tag) method. Default: Resolve .

// ObjectResolveByTagMethodName = GetService
             DI.Setup("Composition")
                 .Bind<IDependency>().To<Dependency>();
             
         or using the API call _Hint(Pure.DI.Hint,System.String)_:
DI.Setup("Composition")
                 .Hint(Hint.ObjectResolveByTagMethodName, "GetService")
                 .Bind<IDependency>().To<Dependency>();
             
Field DisposeMethodModifiers

Modifier override for Dispose() method. Default: public .

// DisposeMethodModifiers = internal
             DI.Setup("Composition")
                 .Bind<IDependency>().To<Dependency>();
             
         or using the API call _Hint(Pure.DI.Hint,System.String)_:
DI.Setup("Composition")
                 .Hint(Hint.DisposeMethodModifiers, "internal")
                 .Bind<IDependency>().To<Dependency>();
             
Field DisposeAsyncMethodModifiers

Modifier override for DisposeAsync() method. Default: public .

// DisposeAsyncMethodModifiers = internal
             DI.Setup("Composition")
                 .Bind<IDependency>().To<Dependency>();
             
         or using the API call _Hint(Pure.DI.Hint,System.String)_:
DI.Setup("Composition")
                 .Hint(Hint.DisposeAsyncMethodModifiers, "internal")
                 .Bind<IDependency>().To<Dependency>();
             
Field FormatCode

Enables/disables code formatting (CPU intensive). Default: Off .

// FormatCode = On
             DI.Setup("Composition")
                 .Bind<IDependency>().To<Dependency>();
             
         or using the API call _Hint(Pure.DI.Hint,System.String)_:
DI.Setup("Composition")
                 .Hint(Hint.FormatCode, "On")
                 .Bind<IDependency>().To<Dependency>();
             
Field SeverityOfNotImplementedContract

Severity level for unimplemented contract errors. Default: Error .

// SeverityOfNotImplementedContract = Warning
             DI.Setup("Composition")
                 .Bind<IDependency>().To<Dependency>();
             
         or using the API call _Hint(Pure.DI.Hint,System.String)_:
DI.Setup("Composition")
                 .Hint(Hint.SeverityOfNotImplementedContract, "Warning")
                 .Bind<IDependency>().To<Dependency>();
             
Field Comments

Enables/disables generated code comments. Default: On .

// Comments = Off
             DI.Setup("Composition")
                 .Bind<IDependency>().To<Dependency>();
             
         or using the API call _Hint(Pure.DI.Hint,System.String)_:
DI.Setup("Composition")
                 .Hint(Hint.Comments, "Off")
                 .Bind<IDependency>().To<Dependency>();
             
Field SkipDefaultConstructor

Enables/disables skipping the default constructor. Default: Off (meaning the default constructor is used when available).

// SkipDefaultConstructor = On
             DI.Setup("Composition")
                 .Bind<IDependency>().To<Dependency>();
             
         or using the API call _Hint(Pure.DI.Hint,System.String)_:
DI.Setup("Composition")
                 .Hint(Hint.UseDefaultConstructor, "Off")
                 .Bind<IDependency>().To<Dependency>();
             
Field SkipDefaultConstructorImplementationTypeNameRegularExpression

Regex filter for types to skip default constructors. Default: .+ .

// SkipDefaultConstructorImplementationTypeNameRegularExpression = Dependency
             DI.Setup("Composition")
                 .Bind<IDependency>().To<Dependency>();
             
         or using the API call _Hint(Pure.DI.Hint,System.String)_:
DI.Setup("Composition")
                 .Hint(Hint.SkipDefaultConstructorImplementationTypeNameRegularExpression, "Dependency")
                 .Bind<IDependency>().To<Dependency>();
             
Field SkipDefaultConstructorImplementationTypeNameWildcard

Wildcard filter for types to skip default constructors. Default: * .

// SkipDefaultConstructorImplementationTypeNameWildcard = *Dependency
             DI.Setup("Composition")
                 .Bind<IDependency>().To<Dependency>();
             
         or using the API call _Hint(Pure.DI.Hint,System.String)_:
DI.Setup("Composition")
                 .Hint(Hint.SkipDefaultConstructorImplementationTypeNameWildcard, "*Dependency")
                 .Bind<IDependency>().To<Dependency>();
             
Field SkipDefaultConstructorLifetimeRegularExpression

Regex filter for lifetimes to skip default constructors. Default: .+ .

// SkipDefaultConstructorLifetimeRegularExpression = Singleton
             DI.Setup("Composition")
                 .Bind<IDependency>().To<Dependency>();
             
         or using the API call _Hint(Pure.DI.Hint,System.String)_:
DI.Setup("Composition")
                 .Hint(Hint.SkipDefaultConstructorLifetimeRegularExpression, "Singleton")
                 .Bind<IDependency>().To<Dependency>();
             
Field SkipDefaultConstructorLifetimeWildcard

Wildcard filter for lifetimes to skip default constructors. Default: * .

// SkipDefaultConstructorLifetimeWildcard = *Singleton
             DI.Setup("Composition")
                 .Bind<IDependency>().To<Dependency>();
             
         or using the API call _Hint(Pure.DI.Hint,System.String)_:
DI.Setup("Composition")
                 .Hint(Hint.SkipDefaultConstructorLifetimeWildcard, "*Singleton")
                 .Bind<IDependency>().To<Dependency>();
             
Field DisableAutoBinding

Disables automatic binding when no explicit binding exists. Default: Off .

// DisableAutoBinding = On
             DI.Setup("Composition")
                 .Bind<IDependency>().To<Dependency>();
             
         or using the API call _Hint(Pure.DI.Hint,System.String)_:
DI.Setup("Composition")
                 .Hint(Hint.DisableAutoBinding, "Off")
                 .Bind<IDependency>().To<Dependency>();
             
Field DisableAutoBindingImplementationTypeNameRegularExpression

Regex filter for implementation types to disable auto-binding. Default: .+ .

// DisableAutoBindingImplementationTypeNameRegularExpression = Dependency
             DI.Setup("Composition")
                 .Hint(Hint.DisableAutoBinding, "Off")
                 .Bind<IDependency>().To<Dependency>();
             
         or using the API call _Hint(Pure.DI.Hint,System.String)_:
DI.Setup("Composition")
                 .Hint(Hint.DisableAutoBinding, "Off")
                 .Hint(Hint.DisableAutoBindingImplementationTypeNameRegularExpression, "Dependency")
                 .Bind<IDependency>().To<Dependency>();
             
Field DisableAutoBindingImplementationTypeNameWildcard

Wildcard filter for implementation types to disable auto-binding. Default: * .

// DisableAutoBindingImplementationTypeNameWildcard = *Dependency
             DI.Setup("Composition")
                 .Hint(Hint.DisableAutoBinding, "Off")
                 .Bind<IDependency>().To<Dependency>();
             
         or using the API call _Hint(Pure.DI.Hint,System.String)_:
DI.Setup("Composition")
                 .Hint(Hint.DisableAutoBinding, "Off")
                 .Hint(Hint.DisableAutoBindingImplementationTypeNameWildcard, "*Dependency")
                 .Bind<IDependency>().To<Dependency>();
             
Field DisableAutoBindingLifetimeRegularExpression

Regex filter for lifetimes to disable auto-binding. Default: .+ .

// DisableAutoBindingLifetimeRegularExpression = Singleton
             DI.Setup("Composition")
                 .Hint(Hint.DisableAutoBinding, "Off")
                 .Bind<IDependency>().To<Dependency>();
             
         or using the API call _Hint(Pure.DI.Hint,System.String)_:
DI.Setup("Composition")
                 .Hint(Hint.DisableAutoBinding, "Off")
                 .Hint(Hint.DisableAutoBindingLifetimeRegularExpression, "Singleton")
                 .Bind<IDependency>().To<Dependency>();
             
Field DisableAutoBindingLifetimeWildcard

Wildcard filter for lifetimes to disable auto-binding. Default: * .

// DisableAutoBindingLifetimeWildcard = *Singleton
             DI.Setup("Composition")
                 .Hint(Hint.DisableAutoBinding, "Off")
                 .Bind<IDependency>().To<Dependency>();
             
         or using the API call _Hint(Pure.DI.Hint,System.String)_:
DI.Setup("Composition")
                 .Hint(Hint.DisableAutoBinding, "Off")
                 .Hint(Hint.DisableAutoBindingLifetimeWildcard, "*Singleton")
                 .Bind<IDependency>().To<Dependency>();
             
IBinding

Defines the API for configuring dependency bindings in the composition.

Method Bind(System.Object[])

Starts binding definition for the implementation type itself. Also binds all directly implemented abstract types excluding special system interfaces. Special system interfaces are excluded from binding: System.ObjectSystem.EnumSystem.MulticastDelegateSystem.DelegateSystem.Collections.IEnumerableSystem.Collections.Generic.IEnumerableSystem.Collections.Generic.IistSystem.Collections.Generic.ICollectionSystem.Collections.IEnumeratorSystem.Collections.Generic.IEnumeratorSystem.Collections.Generic.IIReadOnlyListSystem.Collections.Generic.IReadOnlyCollectionSystem.IDisposableSystem.IAsyncResultSystem.AsyncCallback

DI.Setup("Composition")
                .Bind().To<Service>();
            
  • parameter tags - Optional tags to associate with this binding.

  • returns Binding configuration interface for method chaining.

See also To``1.

See also To1(System.Func{Pure.DI.IContext,0}).

See also !:To<T1,T>().

See also !:To<T1,T2,T>().

See also Tags(System.Object[]).

See also As(Pure.DI.Lifetime).

Method Bind``1(System.Object[])

Starts binding definition for a specific dependency type.

DI.Setup("Composition")
                .Bind<IDependency>().To<Dependency>();
            

Dependency type to bind. Supports type markers like TT and TTList`1.

  • parameter tags - Optional tags to associate with this binding.

  • returns Binding configuration interface for method chaining.

See also To``1.

See also To1(System.Func{Pure.DI.IContext,0}).

See also !:To<T1,T>().

See also !:To<T1,T2,T>().

See also Tags(System.Object[]).

See also As(Pure.DI.Lifetime).

Method Bind``2(System.Object[])

Starts binding definition for multiple dependency types simultaneously. See Bind``1(System.Object[]) for detailed usage. First dependency type to bind.Second dependency type to bind.

  • parameter tags - Optional tags to associate with these bindings.

  • returns Binding configuration interface for method chaining.

See also To``1.

See also To1(System.Func{Pure.DI.IContext,0}).

See also !:To<T1,T>().

See also !:To<T1,T2,T>().

See also Tags(System.Object[]).

See also As(Pure.DI.Lifetime).

Method Bind``3(System.Object[])

Starts binding definition for multiple dependency types simultaneously. See Bind``1(System.Object[]) for detailed usage. First dependency type to bind.Second dependency type to bind.Third dependency type to bind.

  • parameter tags - Optional tags to associate with these bindings.

  • returns Binding configuration interface for method chaining.

See also To``1.

See also To1(System.Func{Pure.DI.IContext,0}).

See also !:To<T1,T>().

See also !:To<T1,T2,T>().

See also Tags(System.Object[]).

See also As(Pure.DI.Lifetime).

Method Bind``4(System.Object[])

Starts binding definition for multiple dependency types simultaneously. See Bind``1(System.Object[]) for detailed usage. First dependency type to bind.Second dependency type to bind.Third dependency type to bind.Fourth dependency type to bind.

  • parameter tags - Optional tags to associate with these bindings.

  • returns Binding configuration interface for method chaining.

See also To``1.

See also To1(System.Func{Pure.DI.IContext,0}).

See also !:To<T1,T>().

See also !:To<T1,T2,T>().

See also Tags(System.Object[]).

See also As(Pure.DI.Lifetime).

Method As(Pure.DI.Lifetime)

Specifies the lifetime scope for the binding.

DI.Setup("Composition")
                .Bind<IDependency>().As(Lifetime.Singleton).To<Dependency>();
            
  • parameter lifetime - Lifetime scope for the binding.

  • returns Binding configuration interface for method chaining.

See also Bind``1(System.Object[]).

See also To``1.

See also To1(System.Func{Pure.DI.IContext,0}).

See also !:To<T1,T>().

See also !:To<T1,T2,T>().

See also Tags(System.Object[]).

Method Tags(System.Object[])

Specifies binding tags to differentiate between multiple implementations of the same interface.

interface IDependency { }
            
             class AbcDependency: IDependency { }
            
             class XyzDependency: IDependency { }
            
             class Dependency: IDependency { }
            
             interface IService
             {
                 IDependency Dependency1 { get; }
                 IDependency Dependency2 { get; }
             }
            
             class Service: IService
             {
                 public Service(
                     [Tag("Abc")] IDependency dependency1,
                     [Tag("Xyz")] IDependency dependency2)
                 {
                     Dependency1 = dependency1;
                     Dependency2 = dependency2;
                 }
            
                 public IDependency Dependency1 { get; }
                 public IDependency Dependency2 { get; }
             }
            
             DI.Setup("Composition")
                 .Bind<IDependency>().Tags("Abc").To<AbcDependency>()
                 .Bind<IDependency>().Tags("Xyz").To<XyzDependency>()
                 .Bind<IService>().To<Service>().Root<IService>("Root");
             
  • parameter tags - Tags to associate with this binding.

  • returns Binding configuration interface for method chaining.

See also Bind``1(System.Object[]).

See also To``1.

See also To1(System.Func{Pure.DI.IContext,0}).

See also !:To<T1,T>().

See also !:To<T1,T2,T>().

See also As(Pure.DI.Lifetime).

Method To``1

Specifies the implementation type for the binding.

DI.Setup("Composition")
                .Bind<IDependency>().To<Dependency>();
            

Implementation type. Supports generic type markers.

  • returns Configuration interface for method chaining.

See also Bind``1(System.Object[]).

See also To1(System.Func{Pure.DI.IContext,0}).

See also !:To<T1,T>().

See also !:To<T1,T2,T>().

See also Tags(System.Object[]).

See also As(Pure.DI.Lifetime).

Method To``1(System.Func{Pure.DI.IContext,``0})

Specifies a factory method to create the implementation instance.

DI.Setup("Composition")
                 .Bind<IService>()
                 To(_ =>
                 {
                     var service = new Service("My Service");
                     service.Initialize();
                     return service;
                 })
            
             // Another example:
             DI.Setup("Composition")
                 .Bind<IService>()
                 To(ctx =>
                 {
                     ctx.Inject<IDependency>(out var dependency);
                     return new Service(dependency);
                 })
            
             // And another example:
             DI.Setup("Composition")
                 .Bind<IService>()
                 To(ctx =>
                 {
                     // Builds up an instance with all necessary dependencies
                     ctx.Inject<Service>(out var service);
                     service.Initialize();
                     return service;
                 })
             
  • parameter factory - Factory method to create and initialize the instance. Implementation type.
  • returns Configuration interface for method chaining.

See also Bind``1(System.Object[]).

See also To``1.

See also !:To<T1,T>().

See also !:To<T1,T2,T>().

See also Tags(System.Object[]).

See also As(Pure.DI.Lifetime). This method is useful for creating and initializing an instance manually. At the compilation stage, the set of dependencies that the object to be created needs is determined. In most cases, this happens automatically, according to the set of constructors and their arguments, and does not require additional customization efforts. But sometimes it is necessary to manually create and/or initialize an object. There are scenarios where manual control over the creation process is required, such as when additional initialization logic is neededwhen complex construction steps are requiredwhen specific object states need to be set during creation

Method To``1(System.String)

Specifies a source code statement to create the implementation.

DI.Setup("Composition")
                .Bind<int>().To<int>("dependencyId")
                .Bind<Func<int, IDependency>>()
                    .To<Func<int, IDependency>>(ctx =>
                        dependencyId =>
                        {
                            ctx.Inject<Dependency>(out var dependency);
                            return dependency;
                        });
            
  • parameter sourceCodeStatement - Source code expression to create the instance. Implementation type.
  • returns Configuration interface for method chaining.

See also Bind``1(System.Object[]).

Method To``2(System.Func{``0,``1})

Specifies a simplified factory method with dependency parameters.

DI.Setup(nameof(Composition))
                 .Bind<IDependency>().To((
                     Dependency dependency) =>
                 {
                     dependency.Initialize();
                     return dependency;
                 });
            
             // Variant using TagAttribute:
             DI.Setup(nameof(Composition))
                 .Bind<IDependency>().To((
                     [Tag("some tag")] Dependency dependency) =>
                 {
                     dependency.Initialize();
                     return dependency;
                 });
             
  • parameter factory - Factory method with injected dependencies. Type of the first dependency parameter.Implementation type.
  • returns Configuration interface for method chaining.

See also Bind``1(System.Object[]).

See also To1(System.Func{Pure.DI.IContext,0}).

See also To``1.

See also Tags(System.Object[]).

See also As(Pure.DI.Lifetime).

Method To``3(System.Func{``0,``1,``2})

Specifies a simplified factory method with multiple dependency parameters.

DI.Setup(nameof(Composition))
                 .Bind<IDependency>().To((
                     Dependency dependency,
                     DateTimeOffset time) =>
                 {
                     dependency.Initialize(time);
                     return dependency;
                 });
            
             // Variant using TagAttribute:
             DI.Setup(nameof(Composition))
                 .Bind("now datetime").To(_ => DateTimeOffset.Now)
                 .Bind<IDependency>().To((
                     Dependency dependency,
                     [Tag("now datetime")] DateTimeOffset time) =>
                 {
                     dependency.Initialize(time);
                     return dependency;
                 });
             
  • parameter factory - Factory method with injected dependencies. Type of the first dependency parameter.Type of second dependency parameter.Implementation type.
  • returns Configuration interface for method chaining.

See also Bind``1(System.Object[]).

See also To1(System.Func{Pure.DI.IContext,0}).

See also To``1.

See also Tags(System.Object[]).

See also As(Pure.DI.Lifetime).

Method To``4(System.Func{``0,``1,``2,``3})

Specifies a simplified factory method with multiple dependency parameters.

  • parameter factory - Factory method with injected dependencies. Type of the first dependency parameter.Type of the second dependency parameter.Type of the third dependency parameter.Implementation type.
  • returns Configuration interface for method chaining.

See also Bind``1(System.Object[]).

See also To1(System.Func{Pure.DI.IContext,0}).

See also To``1.

See also Tags(System.Object[]).

See also As(Pure.DI.Lifetime).

IConfiguration

Defines an API for configuring Dependency Injection bindings.

See also Setup(System.String,Pure.DI.CompositionKind).

Method Bind(System.Object[])

Starts binding definition for the implementation type itself. Also binds all directly implemented abstract types excluding special system interfaces. Special system interfaces are excluded from binding: System.ObjectSystem.EnumSystem.MulticastDelegateSystem.DelegateSystem.Collections.IEnumerableSystem.Collections.Generic.IEnumerableSystem.Collections.Generic.IListSystem.Collections.Generic.ICollectionSystem.Collections.IEnumeratorSystem.Collections.Generic.IEnumeratorSystem.Collections.Generic.IIReadOnlyListSystem.Collections.Generic.IReadOnlyCollectionSystem.IDisposableSystem.IAsyncResultSystem.AsyncCallback

DI.Setup("Composition")
                .Bind().To<Service>();
            
  • parameter tags - Optional tags to associate with the binding.

  • returns Binding configuration interface for method chaining.

See also To``1.

See also To1(System.Func{Pure.DI.IContext,0}).

See also To<T1,T>().

See also To<T1,T2,T>().

See also Tags(System.Object[]).

See also As(Pure.DI.Lifetime).

Method Bind``1(System.Object[])

Starts binding definition for a specific dependency type.

DI.Setup("Composition")
                .Bind<IService>().To<Service>();
            

Dependency type to bind.

  • parameter tags - Optional tags to associate with the binding.

  • returns Binding configuration interface for method chaining.

See also To``1.

See also To1(System.Func{Pure.DI.IContext,0}).

See also To<T1,T>().

See also To<T1,T2,T>().

See also Tags(System.Object[]).

See also As(Pure.DI.Lifetime).

Method Bind``2(System.Object[])

Starts binding definition for multiple dependency types simultaneously. See Bind``1(System.Object[]) for detailed usage. First dependency type to bind.Second dependency type to bind.

  • parameter tags - Optional tags to associate with the binding.

  • returns Binding configuration interface for method chaining.

See also To``1.

See also To1(System.Func{Pure.DI.IContext,0}).

See also To<T1,T>().

See also To<T1,T2,T>().

See also Tags(System.Object[]).

        seealso cref="IBinding.As"/>
Method Bind``3(System.Object[])

Starts binding definition for multiple dependency types simultaneously. See Bind``1(System.Object[]) for detailed usage. First dependency type to bind.Second dependency type to bind.Third dependency type to bind.

  • parameter tags - Optional tags to associate with the binding.

  • returns Binding configuration interface for method chaining.

See also To``1.

See also To1(System.Func{Pure.DI.IContext,0}).

See also To<T1,T>().

See also To<T1,T2,T>().

See also Tags(System.Object[]).

See also As(Pure.DI.Lifetime).

Method Bind``4(System.Object[])

Starts binding definition for multiple dependency types simultaneously. See Bind``1(System.Object[]) for detailed usage. First dependency type to bind.Second dependency type to bind.Third dependency type to bind.Fourth dependency type to bind.

  • parameter tags - Optional tags to associate with the binding.

  • returns Binding configuration interface for method chaining.

See also To``1.

See also To1(System.Func{Pure.DI.IContext,0}).

See also To<T1,T>().

See also To<T1,T2,T>().

See also Tags(System.Object[]).

See also As(Pure.DI.Lifetime).

Method RootBind``1(System.String,Pure.DI.RootKinds,System.Object[])

Starts binding definition with automatic root creation for a dependency type.

DI.Setup("Composition")
                .RootBind<IService>();
            

Dependency type to bind and expose as root.

  • parameter name - Root name template (supports {type}, {TYPE}, {tag} placeholders). Empty name creates a private root accessible only via Resolve methods.

  • parameter kind - Specifies root accessibility and creation method.

  • parameter tags - Tags for binding (first tag used for {tag} placeholder).

  • returns Binding configuration interface for method chaining.

See also To``1.

See also To1(System.Func{Pure.DI.IContext,0}).

See also To<T1,T>().

See also To<T1,T2,T>().

See also Tags(System.Object[]).

See also As(Pure.DI.Lifetime).

Method DependsOn(System.String[])

Specifies base setups to inherit bindings from.

DI.Setup("Composition")
                .DependsOn(nameof(CompositionBase));
            
  • parameter setupNames - Names of base composition setups.

  • returns Configuration interface for method chaining.

See also Setup(System.String,Pure.DI.CompositionKind).

Method GenericTypeArgumentAttribute``1

Registers custom generic type markers.

[AttributeUsage(AttributeTargets.Interface | AttributeTargets.Class | AttributeTargets.Struct)]
             class MyGenericTypeArgumentAttribute: Attribute;
            
             [MyGenericTypeArgument]
             interface TTMy;
            
             DI.Setup("Composition")
                 .GenericTypeAttribute<MyGenericTypeArgumentAttribute>()
                 .Bind<IDependency<TTMy>>().To<Dependency<TTMy>>();
             

Custom attribute type.

  • returns Configuration interface for method chaining.

See also GenericTypeArgumentAttribute``1.

Method TypeAttribute``1(System.Int32)

Registers a custom attribute to override injection types.

DI.Setup("Composition")
                .TypeAttribute<MyTypeAttribute>();
            
  • parameter typeArgumentPosition - Position of type parameter in attribute constructor (default: 0). Custom attribute type.
  • returns Configuration interface for method chaining.

See also TypeAttribute.

Method TagAttribute``1(System.Int32)

Registers a custom attribute to override injection tags.

DI.Setup("Composition")
                .TagAttribute<MyTagAttribute>();
            
  • parameter tagArgumentPosition - Position of tag parameter in attribute constructor (default: 0). Custom attribute type.
  • returns Configuration interface for method chaining.

See also TagAttribute.

Method OrdinalAttribute``1(System.Int32)

Registers a custom attribute to override injection priority.

DI.Setup("Composition")
                .OrdinalAttribute<MyOrdinalAttribute>();
            
  • parameter ordinalArgumentPosition - Position of ordinal parameter in attribute constructor (default: 0). Custom attribute type.
  • returns Configuration interface for method chaining.

See also OrdinalAttribute.

Method DefaultLifetime(Pure.DI.Lifetime)

Sets the default lifetime for the following bindings.

DI.Setup("Composition")
                .DefaultLifetime(Lifetime.Singleton);
            
  • parameter lifetime - Default lifetime to apply.

  • returns Configuration interface for method chaining.

See also Lifetime.

See also As(Pure.DI.Lifetime).

Method DefaultLifetime``1(Pure.DI.Lifetime,System.Object[])

Sets the default lifetime for bindings of specific types for the following bindings.

DI.Setup("Composition")
                .DefaultLifetime<IMySingleton>(Lifetime.Singleton);
            
DI.Setup("Composition")
                .DefaultLifetime<IMySingleton>(Lifetime.Singleton, "my tag");
            
  • parameter lifetime - Default lifetime to apply.

  • parameter tags - Tags specifying which bindings to apply this lifetime to. Type filter for applicable bindings.

  • returns Configuration interface for method chaining.

See also Lifetime.

See also As(Pure.DI.Lifetime).

Method Arg``1(System.String,System.Object[])

Adds a composition argument to be injected.

DI.Setup("Composition")
                .Arg<int>("id");
            

Argument type.

  • parameter name - Argument name template (supports {type}, {TYPE}, {tag} placeholders).

  • parameter tags - Tags to associate with the argument.

  • returns Configuration interface for method chaining.

See also RootArg``1(System.String,System.Object[]).

Method RootArg``1(System.String,System.Object[])

Adds a root argument to be injected.

DI.Setup("Composition")
                .RootArg<int>("id");
            

Argument type.

  • parameter name - Argument name template (supports {type}, {TYPE}, {tag} placeholders).

  • parameter tags - Tags to associate with the argument.

  • returns Configuration interface for method chaining.

See also Arg``1(System.String,System.Object[]).

Method Root``1(System.String,System.Object,Pure.DI.RootKinds)

Defines the composition root.

DI.Setup("Composition")
                .Root<Service>("MyService");
            
DI.Setup("Composition")
                .Root<Service>("My{type}");
            

Root type to expose.

  • parameter name - Root name template (supports {type}, {TYPE}, {tag} placeholders). Empty name creates the private root accessible only via Resolve methods.

  • parameter tag - Tag to associate with the root.

  • parameter kind - Specifies root accessibility and creation method.

  • returns Configuration interface for method chaining.

See also RootBind``1(System.String,Pure.DI.RootKinds,System.Object[]).

See also Roots``1(System.String,Pure.DI.RootKinds,System.String).

Method Roots``1(System.String,Pure.DI.RootKinds,System.String)

Automatically creates roots for all base type implementations found at the time the method is called.

DI.Setup("Composition")
                .Roots<IService>();
            
DI.Setup("Composition")
                .Roots<IService>("Root{type}", filter: "*MyService");
            

Base type for auto-root discovery.

  • parameter name - Root name template (supports {type}, {TYPE} placeholders). Empty name creates private roots accessible only via Resolve methods.

  • parameter kind - Specifies root accessibility and creation method.

  • parameter filter - Wildcard pattern to filter types by full name.

  • returns Configuration interface for method chaining.

See also Root``1(System.String,System.Object,Pure.DI.RootKinds).

Method Builder``1(System.String,Pure.DI.RootKinds)

Defines a builder method for initializing instances post-creation.

DI.Setup("Composition")
                .Builder<Service>("BuildUpMyService");
            

Type the builder method applies to.

  • parameter name - Builder method name template (supports {type}, {TYPE} placeholders). Default: "BuildUp".

  • parameter kind - Specifies builder accessibility.

  • returns Configuration interface for method chaining.

See also Builders``1(System.String,Pure.DI.RootKinds,System.String).

Method Builders``1(System.String,Pure.DI.RootKinds,System.String)

Automatically creates builders for all discoverable implementations of a base type found at the time the method is called.

DI.Setup("Composition")
                .Builders<Service>();
            
DI.Setup("Composition")
                .Builder<Service>("BuildUp");
            
DI.Setup("Composition")
                .Builder<Service>("BuildUp{type}", filter: "*MyService");
            

Base type for builder discovery.

  • parameter name - Builder method name template (supports {type}, {TYPE} placeholders). Default: "BuildUp".

  • parameter kind - Specifies builder accessibility.

  • parameter filter - Wildcard pattern to filter types by full name.

  • returns Configuration interface for method chaining.

See also Builder``1(System.String,Pure.DI.RootKinds).

Method Hint(Pure.DI.Hint,System.String)

Configures code generation options.

DI.Setup("Composition")
                .Hint(Resolve, "Off");
            
  • parameter hint - Hint type to configure.

  • parameter value - Value to set for the hint.

  • returns Configuration interface for method chaining.

See also Hint.

Method Accumulate``2(Pure.DI.Lifetime[])

Registers an accumulator for collecting instances of specific lifetimes. If no lifetime is specified, it works for all.

DI.Setup("Composition")
                .Accumulate<IDisposable, MyAccumulator>(Lifetime.Transient);
            
  • parameter lifetimes - Lifetimes of instances to accumulate. Type of instances to collect.Accumulator type (requires parameterless constructor and Add(T) method).

  • returns Configuration interface for method chaining.

See also Lifetime.

Method GenericTypeArgument``1

Defines a generic type marker for generic bindings.

interface TTMy;
            
             DI.Setup("Composition")
                 .GenericTypeArgument<TTMy>()
                 .Bind<IDependency<TTMy>>().To<Dependency<TTMy>>();
             

Generic type marker.

  • returns Configuration interface for method chaining.

See also GenericTypeArgumentAttribute``1.

IContext

Injection context. Cannot be used outside the binding setup.

Property Tag

The tag that was used to inject the current object in the object graph. Cannot be used outside the binding setup. See also Tags(System.Object[])

DI.Setup("Composition")
                .Bind<Lazy<TT>>()
                .To(ctx =>
                {
                    ctx.Inject<Func<TT>>(ctx.Tag, out var func);
                    return new Lazy<TT>(func, false);
                };
            

See also To1(System.Func{Pure.DI.IContext,0}).

See also Tags(System.Object[]).

Property ConsumerTypes

The chain of consumer types for which an instance is created, from the immediate consumer down to the composition type. Cannot be used outside the binding setup. Guaranteed to contain at least one element.

var box = new Composition().Box;
             // Output: ShroedingersCat, CardboardBox`1, Composition
            
             static void Setup() =>
                 DI.Setup(nameof(Composition))
                 .Bind().To(ctx => new Log(ctx.ConsumerTypes))
                 .Bind().To<ShroedingersCat>()
                 .Bind().To<CardboardBox<TT>>()
                 .Root<CardboardBox<ShroedingersCat>>("Box");
            
             public class Log
             {
                 public Log(Type[] types) =>
                     Console.WriteLine(string.Join(", ", types.Select(type => type.Name)));
             }
            
             public record CardboardBox<T>(T Content);
            
             public record ShroedingersCat(Log log);
             

See also ConsumerType.

See also To1(System.Func{Pure.DI.IContext,0}).

Property ConsumerType

The immediate consumer type for which the instance is created. Cannot be used outside the binding setup.

var box = new Composition().Box;
             // Output: ShroedingersCat
            
             static void Setup() =>
                 DI.Setup(nameof(Composition))
                 .Bind().To(ctx => new Log(ctx.ConsumerType))
                 .Bind().To<ShroedingersCat>()
                 .Bind().To<CardboardBox<TT>>()
                 .Root<CardboardBox<ShroedingersCat>>("Box");
            
             public class Log
             {
                 public Log(Type type) =>
                     Console.WriteLine(type.Name);
             }
            
             public record CardboardBox<T>(T Content);
            
             public record ShroedingersCat(Log log);
             

See also ConsumerTypes.

See also To1(System.Func{Pure.DI.IContext,0}).

Property Lock

Gets the synchronization object used to control thread-safe access during composition. Used to prevent race conditions during dependency resolution and override operations.

DI.Setup(nameof(Composition))
                .Bind<IDependency>().To<IDependency>(ctx =>
                {
                    lock (ctx.Lock)
                    {
                        ctx.Inject(out Dependency dependency);
                        dependency.Initialize();
                        return dependency;
                    }
                })
            
Method Inject``1(``0@)

Injects an instance of type T . Cannot be used outside the binding setup.

DI.Setup("Composition")
                 .Bind<IService>()
                 To(ctx =>
                 {
                     ctx.Inject<IDependency>(out var dependency);
                     return new Service(dependency);
                 })
             
         and another example:
DI.Setup("Composition")
                 .Bind<IService>()
                 To(ctx =>
                 {
                     // Builds up an instance with all necessary dependencies
                     ctx.Inject<Service>(out var service);
            
                     service.Initialize();
                     return service;
                 })
             
  • parameter value - Injectable instance. . Instance type. See also To1(System.Func{Pure.DI.IContext,0}).
Method Inject``1(System.Object,``0@)

Injects an instance of type T marked with a tag. Cannot be used outside the binding setup.

DI.Setup("Composition")
                .Bind<IService>()
                To(ctx =>
                {
                    ctx.Inject<IDependency>("MyTag", out var dependency);
                    return new Service(dependency);
                })
            
  • parameter tag - The injection tag. See also Tags(System.Object[]) .

  • parameter value - Injectable instance. . Instance type. See also To1(System.Func{Pure.DI.IContext,0}).

Method BuildUp``1(``0)

Builds up of an existing object. In other words, injects the necessary dependencies via methods, properties, or fields into an existing object. Cannot be used outside the binding setup.

DI.Setup("Composition")
                .Bind<IService>()
                To(ctx =>
                {
                    var service = new Service();
                    // Initialize an instance with all necessary dependencies
                    ctx.BuildUp(service);
                    return service;
                })
            
  • parameter value - An existing object for which the injection(s) is to be performed. Object type. See also To1(System.Func{Pure.DI.IContext,0}).
Method Override``1(``0,System.Object[])

Overrides the binding with the specified value. Cannot be used outside the binding setup.

DI.Setup("Composition")
                .Bind().To<Func<int, int, IDependency>>(ctx =>
                    (dependencyId, subId) =>
                    {
                        // Overrides with a lambda argument
                        ctx.Override(dependencyId);
                        // Overrides with tag using lambda argument
                        ctx.Override(subId, "sub");
                        // Overrides with some value
                        ctx.Override($"Dep {dependencyId} {subId}");
                        // Overrides with injected value
                        ctx.Inject(Tag.Red, out Color red);
                        ctx.Override(red);
                        ctx.Inject<Dependency>(out var dependency);
                        return dependency;
                    })
            
        Overrides uses a shared state to override values. And if this code is supposed to run in multiple threads at once, then you need to ensure their synchronization, for example
DI.Setup("Composition")
                .Bind().To<Func<int, int, IDependency>>(ctx =>
                    (dependencyId, subId) =>
                    {
                        lock (ctx.Lock)
                        {
                            // Overrides with a lambda argument
                            ctx.Override(dependencyId);
                            // Overrides with tag using lambda argument
                            ctx.Override(subId, "sub");
                            // Overrides with some value
                            ctx.Override($"Dep {dependencyId} {subId}");
                            // Overrides with injected value
                            ctx.Inject(Tag.Red, out Color red);
                            ctx.Override(red);
                            ctx.Inject<Dependency>(out var dependency);
                            return dependency;
                        }
                    })
            
        An alternative to synchronizing thread yourself is to use types like _Func`3_this. There, threads synchronization is performed automatically.
  • parameter value - The object that will be used to override a binding. Object type that will be used to override a binding.
  • parameter tags - Injection tags that will be used to override a binding. See also Tags(System.Object[]) .

See also To(System.Func<TArg1,T>).

IOwned

Represents an owned resource whose lifetime is managed by its owner. Provides both synchronous and asynchronous disposal capabilities for proper resource cleanup.

See also Owned.

See also Accumulate``2(Pure.DI.Lifetime[]).

Lifetime

Defines binding lifetimes for dependencies. Binding as Singleton:

DI.Setup("Composition")
                .Bind<IDependency>().As(Lifetime.Singleton).To<Dependency>();
            

See also Setup(System.String,Pure.DI.CompositionKind).

See also As(Pure.DI.Lifetime).

See also DefaultLifetime(Pure.DI.Lifetime).

See also DefaultLifetime``1(Pure.DI.Lifetime,System.Object[]).

Field Transient

Creates a new dependency instance for each injection (default behavior). Default behavior can be changed by DefaultLifetime(Pure.DI.Lifetime) and DefaultLifetime``1(Pure.DI.Lifetime,System.Object[]). Explicit transient binding:

DI.Setup("Composition")
                .Bind<IDependency>().As(Lifetime.Transient).To<Dependency>();
            
        Default behavior (equivalent):
DI.Setup("Composition")
                .Bind<IDependency>().To<Dependency>();
            

See also DefaultLifetime(Pure.DI.Lifetime).

See also DefaultLifetime``1(Pure.DI.Lifetime,System.Object[]).

Field Singleton

Maintains a single instance per composition. Singleton binding:

DI.Setup("Composition")
                .Bind<IService>().As(Lifetime.Singleton).To<Service>();
            
Field PerResolve

Single instance per composition root. Per-resolve binding:

DI.Setup("Composition")
                .Bind<IProcessor>().As(Lifetime.PerResolve).To<Processor>();
            
Field PerBlock

Reuses instances within code blocks to reduce allocations. Per-block binding:

DI.Setup("Composition")
                .Bind<ILogger>().As(Lifetime.PerBlock).To<Logger>();
            
Field Scoped

Single instance per dependency scope. Scoped binding:

DI.Setup("Composition")
                .Bind<IDatabase>().As(Lifetime.Scoped).To<Database>();
            
Name

Provides well-known names used throughout the dependency injection configuration. These names serve as standardized identifiers for common DI components and behaviors.

OrdinalAttribute

Specifies injection order priority for constructors, methods, properties, and fields. While this attribute is part of the DI API, you can implement custom ordering attributes in any namespace. For constructors, it defines the sequence of attempts to use a particular constructor to create an object:

class Service: IService
             {
                 private readonly string _name;
            
                 [Ordinal(1)]
                 public Service(IDependency dependency) =>
                     _name = "with dependency";
            
                 [Ordinal(0)]
                 public Service(string name) => _name = name;
             }
             
         For fields, properties and methods, it specifies to perform dependency injection and defines the sequence:
class Person: IPerson
             {
                 private readonly string _name = "";
            
                 [Ordinal(0)]
                 public int Id;
            
                 [Ordinal(1)]
                 public string FirstName
                 {
                     set
                     {
                         _name = value;
                     }
                 }
            
                 public IDependency? Dependency { get; private set; }
            
                 [Ordinal(2)]
                 public void SetDependency(IDependency dependency) =>
                     Dependency = dependency;
             }
             

See also DependencyAttribute.

See also TagAttribute.

See also TypeAttribute.

Constructor OrdinalAttribute(System.Int32)

Initializes an attribute instance with the specified injection priority.

  • parameter ordinal - Lower values indicate higher priority (0 executes before 1). Default: 0.
Owned

Manages lifetime of disposable objects by accumulating them and providing deterministic disposal. Implements both synchronous and asynchronous disposal patterns for comprehensive resource cleanup.

See also IOwned.

See also Accumulate``2(Pure.DI.Lifetime[]).

Method Dispose
Owned`1

Represents an owned resource of type that combines a value with its disposal mechanism. Provides deterministic lifetime management through both synchronous and asynchronous disposal patterns. The type of the owned value. See also IOwned.

See also Owned.

See also Accumulate``2(Pure.DI.Lifetime[]).

Field Value

The owned value instance.

Constructor Owned`1(`0,Pure.DI.IOwned)

Initializes a new owned value with its associated disposal mechanism.

  • parameter value - The value to be owned and managed.

  • parameter owned - The disposal mechanism responsible for cleaning up the owned value.

Method Dispose
Pair`1

For internal use.

RootKinds

Specifies configuration flags for composition root members, controlling their access level, modifiers, and representation. Flags can be combined to define complex root behaviors.

See also Root``1(System.String,System.Object,Pure.DI.RootKinds).

See also RootBind``1(System.String,Pure.DI.RootKinds,System.Object[]).

See also Roots``1(System.String,Pure.DI.RootKinds,System.String).

See also Builder``1(System.String,Pure.DI.RootKinds).

See also Builders``1(System.String,Pure.DI.RootKinds,System.String).

Field Default

Default configuration: Public access modifier and property representation.

Field Public

Public access modifier for the composition root.

Field Internal

Internal access modifier for the composition root.

Field Private

Private access modifier for the composition root.

Field Property

Represents the composition root as a property.

Field Method

Represents the composition root as a method.

Field Static

Defines the composition root as static.

Field Partial

Defines the composition root as partial.

Field Exposed

Exposes the root for external binding via attributes.

See also BindAttribute.

Field Protected

Protected access modifier for the composition root.

Field Virtual

Applies virtual modifier to enable overriding in derived classes.

Field Override

Applies override modifier to redefine a base implementation.

Tag

Provides standardized tags for dependency binding scenarios, including special tags for unique bindings, type-based identification, and injection targeting.

See also Bind``1(System.Object[]).

See also Tags(System.Object[]).

Field Unique

Enables multiple distinct bindings for the same instance type. Used for collection injection.

DI.Setup("Composition")
                .Bind<IService>(Tag.Unique).To<Service1>()
                .Bind<IService>(Tag.Unique).To<Service1>()
                .Root<IEnumerable<IService>>("Root");
            
Field Type

Tags bindings by their implementation type for explicit injection.

DI.Setup("Composition")
                .Bind<IService>(Tag.Type).To<Service>()
                .Root<IService>("Root", typeof(Service));
            
Field Any

Matches any tag during resolution. Used for conditional bindings that accept any tag.

DI.Setup("Composition")
             DI.Setup(nameof(Composition))
                 .Bind<IDependency>(Tag.Any).To(ctx => new Dependency(ctx.Tag))
                 .Bind<IService>().To<Service>()
            
Method On(System.String[])

Creates a tag targeting specific injection sites using member identifiers.

DI.Setup("Composition")
                .Bind(Tag.On("MyNamespace.Service.Service:dep"))
                    .To<Dependency>()
                .Bind().To<Service>()
                .Root<<IService>("Root");
            
  • parameter injectionSites - Member identifiers in format: [namespace].[type].[member][:argument]. Case-sensitive. Wildcards (*, ?) supported. Omit 'global::'.
Method OnConstructorArg``1(System.String)

Creates a tag targeting a specific constructor parameter by name.

DI.Setup("Composition")
                .Bind(Tag.OnConstructorArg<Service>("dep"))
                    .To<Dependency>()
                .Bind().To<Service>()
                .Root<IService>("Root");
            
  • parameter argName - Constructor parameter name
Method OnMember``1(System.String)

Creates a tag targeting a specific field or property by name.

DI.Setup("Composition")
                .Bind(Tag.OnMember<Service>("DepProperty"))
                    .To<Dependency>()
                .Bind().To<Service>()
                .Root<IService>("Root");
            
  • parameter memberName - Field or property name
Method OnMethodArg``1(System.String,System.String)

Creates a tag targeting a specific method parameter by method and argument names.

DI.Setup("Composition")
                .Bind(Tag.OnMethodArg<Service>("DoSomething", "state"))
                    .To<Dependency>()
                .Bind().To<Service>()
                .Root<IService>("Root");
            
  • parameter methodName - Method name

  • parameter argName - Parameter name

Field VarName

Atomically generated smart tag with value "VarName". It's used for:

        class _Generator__VarsMap_ <-- _IIdGenerator_(VarName) -- _IdGenerator_ as _Transient_
Field UsingDeclarations

Atomically generated smart tag with value "UsingDeclarations". It's used for:

        class _Generator__CompositionClassBuilder_ <-- _IBuilder{TData, T}_(UsingDeclarations) -- _UsingDeclarationsBuilder_ as _PerBlock_
Field Overrider

Atomically generated smart tag with value "Overrider". It's used for:

        class _Generator__DependencyGraphBuilder_ <-- _IGraphRewriter_(Overrider) -- _GraphOverrider_ as _PerBlock_
Field CompositionClass

Atomically generated smart tag with value "CompositionClass". It's used for:

        class _Generator__CodeBuilder_ <-- _IBuilder{TData, T}_(CompositionClass) -- _CompositionClassBuilder_ as _PerBlock_
Field UniqueTag

Atomically generated smart tag with value "UniqueTag". It's used for:

        class _Generator__ApiInvocationProcessor_ <-- (UniqueTag) -- _IdGenerator_ as _PerResolve__BindingBuilder_ <-- _IIdGenerator_(UniqueTag) -- _IdGenerator_ as _PerResolve_
Field Cleaner

Atomically generated smart tag with value "Cleaner". It's used for:

        class _Generator__DependencyGraphBuilder_ <-- _IGraphRewriter_(Cleaner) -- _GraphCleaner_ as _PerBlock_
Field Override

Atomically generated smart tag with value "Override". It's used for:

        class _Generator__OverrideIdProvider_ <-- _IIdGenerator_(Override) -- _IdGenerator_ as _PerResolve_
TagAttribute

Represents a tag attribute overriding an injection tag. The tag can be a constant, a type, or a value of an enumerated type. This attribute is part of the API, but you can use your own attribute at any time, and this allows you to define them in the assembly and namespace you want. Sometimes it's important to take control of building a dependency graph. For example, when there are multiple implementations of the same contract. In this case, tags will help:

interface IDependency { }
             
            
             class AbcDependency: IDependency { }
             
            
             class XyzDependency: IDependency { }
             
            
             class Dependency: IDependency { }
             
            
             interface IService
             {
                 IDependency Dependency1 { get; }
             
            
                 IDependency Dependency2 { get; }
             }
            
             
             class Service: IService
             {
                 public Service(
                     [Tag("Abc")] IDependency dependency1,
                     [Tag("Xyz")] IDependency dependency2)
                 {
                     Dependency1 = dependency1;
                     Dependency2 = dependency2;
                 }
            
                 public IDependency Dependency1 { get; }
            
             
                 public IDependency Dependency2 { get; }
             }
            
             
             DI.Setup("Composition")
                 .Bind<IDependency>("Abc").To<AbcDependency>()
                 .Bind<IDependency>("Xyz").To<XyzDependency>()
                 .Bind<IService>().To<Service>().Root<IService>("Root");
             

See also DependencyAttribute.

See also OrdinalAttribute.

See also TypeAttribute.

Constructor TagAttribute(System.Object)

Creates an attribute instance.

  • parameter tag - The injection tag. See also Tags(System.Object[]) .
TT

Represents the generic type arguments marker for a reference type.

DI.Setup("Composition")
                .Bind<IDependency<TT>>().To<Dependency<TT>>();
            
TT1

Represents the generic type arguments marker for a reference type.

DI.Setup("Composition")
                .Bind<IDependency<TT1>>().To<Dependency<TT1>>();
            
TT2

Represents the generic type arguments marker for a reference type.

DI.Setup("Composition")
                .Bind<IDependency<TT2>>().To<Dependency<TT2>>();
            
TT3

Represents the generic type arguments marker for a reference type.

DI.Setup("Composition")
                .Bind<IDependency<TT3>>().To<Dependency<TT3>>();
            
TT4

Represents the generic type arguments marker for a reference type.

DI.Setup("Composition")
                .Bind<IDependency<TT4>>().To<Dependency<TT4>>();
            
TTCollection`1

Represents the generic type arguments marker for ICollection`1.

DI.Setup("Composition")
                .Bind<IDependency<TTCollection<TT>>>().To<Dependency<TTCollection<TT>>>();
            
TTCollection1`1

Represents the generic type arguments marker for ICollection`1.

DI.Setup("Composition")
                .Bind<IDependency<TTCollection1<TT>>>().To<Dependency<TTCollection1<TT>>>();
            
TTCollection2`1

Represents the generic type arguments marker for ICollection`1.

DI.Setup("Composition")
                .Bind<IDependency<TTCollection2<TT>>>().To<Dependency<TTCollection2<TT>>>();
            
TTCollection3`1

Represents the generic type arguments marker for ICollection`1.

DI.Setup("Composition")
                .Bind<IDependency<TTCollection3<TT>>>().To<Dependency<TTCollection3<TT>>>();
            
TTCollection4`1

Represents the generic type arguments marker for ICollection`1.

DI.Setup("Composition")
                .Bind<IDependency<TTCollection4<TT>>>().To<Dependency<TTCollection4<TT>>>();
            
TTComparable

Represents the generic type arguments marker for IComparable.

DI.Setup("Composition")
                .Bind<IDependency<TTComparable>>().To<Dependency<TTComparable>>();
            
TTComparable`1

Represents the generic type arguments marker for IComparable`1.

DI.Setup("Composition")
                .Bind<IDependency<TTComparable<TT>>>().To<Dependency<TTComparable<TT>>>();
            
TTComparable1

Represents the generic type arguments marker for IComparable.

DI.Setup("Composition")
                .Bind<IDependency<TTComparable1>>().To<Dependency<TTComparable1>>();
            
TTComparable1`1

Represents the generic type arguments marker for IComparable`1.

DI.Setup("Composition")
                .Bind<IDependency<TTComparable1<TT>>>().To<Dependency<TTComparable1<TT>>>();
            
TTComparable2

Represents the generic type arguments marker for IComparable.

DI.Setup("Composition")
                .Bind<IDependency<TTComparable2>>().To<Dependency<TTComparable2>>();
            
TTComparable2`1

Represents the generic type arguments marker for IComparable`1.

DI.Setup("Composition")
                .Bind<IDependency<TTComparable2<TT>>>().To<Dependency<TTComparable2<TT>>>();
            
TTComparable3

Represents the generic type arguments marker for IComparable.

DI.Setup("Composition")
                .Bind<IDependency<TTComparable3>>().To<Dependency<TTComparable3>>();
            
TTComparable3`1

Represents the generic type arguments marker for IComparable`1.

DI.Setup("Composition")
                .Bind<IDependency<TTComparable3<TT>>>().To<Dependency<TTComparable3<TT>>>();
            
TTComparable4

Represents the generic type arguments marker for IComparable.

DI.Setup("Composition")
                .Bind<IDependency<TTComparable4>>().To<Dependency<TTComparable4>>();
            
TTComparable4`1

Represents the generic type arguments marker for IComparable`1.

DI.Setup("Composition")
                .Bind<IDependency<TTComparable4<TT>>>().To<Dependency<TTComparable4<TT>>>();
            
TTComparer`1

Represents the generic type arguments marker for IComparer`1.

DI.Setup("Composition")
                .Bind<IDependency<TTComparer<TT>>>().To<Dependency<TTComparer<TT>>>();
            
TTComparer1`1

Represents the generic type arguments marker for IComparer`1.

DI.Setup("Composition")
                .Bind<IDependency<TTComparer1<TT>>>().To<Dependency<TTComparer1<TT>>>();
            
TTComparer2`1

Represents the generic type arguments marker for IComparer`1.

DI.Setup("Composition")
                .Bind<IDependency<TTComparer2<TT>>>().To<Dependency<TTComparer2<TT>>>();
            
TTComparer3`1

Represents the generic type arguments marker for IComparer`1.

DI.Setup("Composition")
                .Bind<IDependency<TTComparer3<TT>>>().To<Dependency<TTComparer3<TT>>>();
            
TTComparer4`1

Represents the generic type arguments marker for IComparer`1.

DI.Setup("Composition")
                .Bind<IDependency<TTComparer4<TT>>>().To<Dependency<TTComparer4<TT>>>();
            
TTDisposable

Represents the generic type arguments marker for IDisposable.

DI.Setup("Composition")
                .Bind<IDependency<TTDisposable>>().To<Dependency<TTDisposable>>();
            
TTDisposable1

Represents the generic type arguments marker for IDisposable.

DI.Setup("Composition")
                .Bind<IDependency<TTDisposable1>>().To<Dependency<TTDisposable1>>();
            
TTDisposable2

Represents the generic type arguments marker for IDisposable.

DI.Setup("Composition")
                .Bind<IDependency<TTDisposable2>>().To<Dependency<TTDisposable2>>();
            
TTDisposable3

Represents the generic type arguments marker for IDisposable.

DI.Setup("Composition")
                .Bind<IDependency<TTDisposable3>>().To<Dependency<TTDisposable3>>();
            
TTDisposable4

Represents the generic type arguments marker for IDisposable.

DI.Setup("Composition")
                .Bind<IDependency<TTDisposable4>>().To<Dependency<TTDisposable4>>();
            
TTE

Represents the generic type arguments marker for a enum type.

DI.Setup("Composition")
                .Bind<IDependency<TTE>>().To<Dependency<TTE>>();
            
TTE1

Represents the generic type arguments marker for a enum type.

DI.Setup("Composition")
                .Bind<IDependency<TTE1>>().To<Dependency<TTE1>>();
            
TTE2

Represents the generic type arguments marker for a enum type.

DI.Setup("Composition")
                .Bind<IDependency<TTE2>>().To<Dependency<TTE2>>();
            
TTE3

Represents the generic type arguments marker for a enum type.

DI.Setup("Composition")
                .Bind<IDependency<TTE3>>().To<Dependency<TTE3>>();
            
TTE4

Represents the generic type arguments marker for a enum type.

DI.Setup("Composition")
                .Bind<IDependency<TTE4>>().To<Dependency<TTE4>>();
            
TTEnumerable`1

Represents the generic type arguments marker for IEnumerable`1.

DI.Setup("Composition")
                .Bind<IDependency<TTEnumerable<TT>>>().To<Dependency<TTEnumerable<TT>>>();
            
TTEnumerable1`1

Represents the generic type arguments marker for IEnumerable`1.

DI.Setup("Composition")
                .Bind<IDependency<TTEnumerable1<TT>>>().To<Dependency<TTEnumerable1<TT>>>();
            
TTEnumerable2`1

Represents the generic type arguments marker for IEnumerable`1.

DI.Setup("Composition")
                .Bind<IDependency<TTEnumerable2<TT>>>().To<Dependency<TTEnumerable2<TT>>>();
            
TTEnumerable3`1

Represents the generic type arguments marker for IEnumerable`1.

DI.Setup("Composition")
                .Bind<IDependency<TTEnumerable3<TT>>>().To<Dependency<TTEnumerable3<TT>>>();
            
TTEnumerable4`1

Represents the generic type arguments marker for IEnumerable`1.

DI.Setup("Composition")
                .Bind<IDependency<TTEnumerable4<TT>>>().To<Dependency<TTEnumerable4<TT>>>();
            
TTEnumerator`1

Represents the generic type arguments marker for IEnumerator`1.

DI.Setup("Composition")
                .Bind<IDependency<TTEnumerator<TT>>>().To<Dependency<TTEnumerator<TT>>>();
            
TTEnumerator1`1

Represents the generic type arguments marker for IEnumerator`1.

DI.Setup("Composition")
                .Bind<IDependency<TTEnumerator1<TT>>>().To<Dependency<TTEnumerator1<TT>>>();
            
TTEnumerator2`1

Represents the generic type arguments marker for IEnumerator`1.

DI.Setup("Composition")
                .Bind<IDependency<TTEnumerator2<TT>>>().To<Dependency<TTEnumerator2<TT>>>();
            
TTEnumerator3`1

Represents the generic type arguments marker for IEnumerator`1.

DI.Setup("Composition")
                .Bind<IDependency<TTEnumerator3<TT>>>().To<Dependency<TTEnumerator3<TT>>>();
            
TTEnumerator4`1

Represents the generic type arguments marker for IEnumerator`1.

DI.Setup("Composition")
                .Bind<IDependency<TTEnumerator4<TT>>>().To<Dependency<TTEnumerator4<TT>>>();
            
TTEqualityComparer`1

Represents the generic type arguments marker for IEqualityComparer`1.

DI.Setup("Composition")
                .Bind<IDependency<TTEqualityComparer<TT>>>().To<Dependency<TTEqualityComparer<TT>>>();
            
TTEqualityComparer1`1

Represents the generic type arguments marker for IEqualityComparer`1.

DI.Setup("Composition")
                .Bind<IDependency<TTEqualityComparer1<TT>>>().To<Dependency<TTEqualityComparer1<TT>>>();
            
TTEqualityComparer2`1

Represents the generic type arguments marker for IEqualityComparer`1.

DI.Setup("Composition")
                .Bind<IDependency<TTEqualityComparer2<TT>>>().To<Dependency<TTEqualityComparer2<TT>>>();
            
TTEqualityComparer3`1

Represents the generic type arguments marker for IEqualityComparer`1.

DI.Setup("Composition")
                .Bind<IDependency<TTEqualityComparer3<TT>>>().To<Dependency<TTEqualityComparer3<TT>>>();
            
TTEqualityComparer4`1

Represents the generic type arguments marker for IEqualityComparer`1.

DI.Setup("Composition")
                .Bind<IDependency<TTEqualityComparer4<TT>>>().To<Dependency<TTEqualityComparer4<TT>>>();
            
TTEquatable`1

Represents the generic type arguments marker for IEquatable`1.

DI.Setup("Composition")
                .Bind<IDependency<TTEquatable<TT>>>().To<Dependency<TTEquatable<TT>>>();
            
TTEquatable1`1

Represents the generic type arguments marker for IEquatable`1.

DI.Setup("Composition")
                .Bind<IDependency<TTEquatable1<TT>>>().To<Dependency<TTEquatable1<TT>>>();
            
TTEquatable2`1

Represents the generic type arguments marker for IEquatable`1.

DI.Setup("Composition")
                .Bind<IDependency<TTEquatable2<TT>>>().To<Dependency<TTEquatable2<TT>>>();
            
TTEquatable3`1

Represents the generic type arguments marker for IEquatable`1.

DI.Setup("Composition")
                .Bind<IDependency<TTEquatable3<TT>>>().To<Dependency<TTEquatable3<TT>>>();
            
TTEquatable4`1

Represents the generic type arguments marker for IEquatable`1.

DI.Setup("Composition")
                .Bind<IDependency<TTEquatable4<TT>>>().To<Dependency<TTEquatable4<TT>>>();
            
TTList`1

Represents the generic type arguments marker for IList`1.

DI.Setup("Composition")
                .Bind<IDependency<TTList<TT>>>().To<Dependency<TTList<TT>>>();
            
TTList1`1

Represents the generic type arguments marker for IList`1.

DI.Setup("Composition")
                .Bind<IDependency<TTList1<TT>>>().To<Dependency<TTList1<TT>>>();
            
TTList2`1

Represents the generic type arguments marker for IList`1.

DI.Setup("Composition")
                .Bind<IDependency<TTList2<TT>>>().To<Dependency<TTList2<TT>>>();
            
TTList3`1

Represents the generic type arguments marker for IList`1.

DI.Setup("Composition")
                .Bind<IDependency<TTList3<TT>>>().To<Dependency<TTList3<TT>>>();
            
TTList4`1

Represents the generic type arguments marker for IList`1.

DI.Setup("Composition")
                .Bind<IDependency<TTList4<TT>>>().To<Dependency<TTList4<TT>>>();
            
TTObservable`1

Represents the generic type arguments marker for IObservable`1.

DI.Setup("Composition")
                .Bind<IDependency<TTObservable<TT>>>().To<Dependency<TTObservable<TT>>>();
            
TTObservable1`1

Represents the generic type arguments marker for IObservable`1.

DI.Setup("Composition")
                .Bind<IDependency<TTObservable1<TT>>>().To<Dependency<TTObservable1<TT>>>();
            
TTObservable2`1

Represents the generic type arguments marker for IObservable`1.

DI.Setup("Composition")
                .Bind<IDependency<TTObservable2<TT>>>().To<Dependency<TTObservable2<TT>>>();
            
TTObservable3`1

Represents the generic type arguments marker for IObservable`1.

DI.Setup("Composition")
                .Bind<IDependency<TTObservable3<TT>>>().To<Dependency<TTObservable3<TT>>>();
            
TTObservable4`1

Represents the generic type arguments marker for IObservable`1.

DI.Setup("Composition")
                .Bind<IDependency<TTObservable4<TT>>>().To<Dependency<TTObservable4<TT>>>();
            
TTObserver`1

Represents the generic type arguments marker for IObserver`1.

DI.Setup("Composition")
                .Bind<IDependency<TTObserver<TT>>>().To<Dependency<TTObserver<TT>>>();
            
TTObserver1`1

Represents the generic type arguments marker for IObserver`1.

DI.Setup("Composition")
                .Bind<IDependency<TTObserver1<TT>>>().To<Dependency<TTObserver1<TT>>>();
            
TTObserver2`1

Represents the generic type arguments marker for IObserver`1.

DI.Setup("Composition")
                .Bind<IDependency<TTObserver2<TT>>>().To<Dependency<TTObserver2<TT>>>();
            
TTObserver3`1

Represents the generic type arguments marker for IObserver`1.

DI.Setup("Composition")
                .Bind<IDependency<TTObserver3<TT>>>().To<Dependency<TTObserver3<TT>>>();
            
TTObserver4`1

Represents the generic type arguments marker for IObserver`1.

DI.Setup("Composition")
                .Bind<IDependency<TTObserver4<TT>>>().To<Dependency<TTObserver4<TT>>>();
            
TTReadOnlyCollection`1

Represents the generic type arguments marker for IReadOnlyCollection`1.

TTReadOnlyCollection1`1

Represents the generic type arguments marker for IReadOnlyCollection`1.

TTReadOnlyCollection2`1

Represents the generic type arguments marker for IReadOnlyCollection`1.

TTReadOnlyCollection3`1

Represents the generic type arguments marker for IReadOnlyCollection`1.

TTReadOnlyCollection4`1

Represents the generic type arguments marker for IReadOnlyCollection`1.

TTReadOnlyList`1

Represents the generic type arguments marker for IReadOnlyList`1.

TTReadOnlyList1`1

Represents the generic type arguments marker for IReadOnlyList`1.

TTReadOnlyList2`1

Represents the generic type arguments marker for IReadOnlyList`1.

TTReadOnlyList3`1

Represents the generic type arguments marker for IReadOnlyList`1.

TTReadOnlyList4`1

Represents the generic type arguments marker for IReadOnlyList`1.

TTS

Represents the generic type arguments marker for a value type.

DI.Setup("Composition")
                .Bind<IDependency<TTS>>().To<Dependency<TTS>>();
            
TTS1

Represents the generic type arguments marker for a value type.

DI.Setup("Composition")
                .Bind<IDependency<TTS1>>().To<Dependency<TTS1>>();
            
TTS2

Represents the generic type arguments marker for a value type.

DI.Setup("Composition")
                .Bind<IDependency<TTS2>>().To<Dependency<TTS2>>();
            
TTS3

Represents the generic type arguments marker for a value type.

DI.Setup("Composition")
                .Bind<IDependency<TTS3>>().To<Dependency<TTS3>>();
            
TTS4

Represents the generic type arguments marker for a value type.

DI.Setup("Composition")
                .Bind<IDependency<TTS4>>().To<Dependency<TTS4>>();
            
TTSet`1

Represents the generic type arguments marker for ISet`1.

DI.Setup("Composition")
                .Bind<IDependency<TTSet<TT>>>().To<Dependency<TTSet<TT>>>();
            
TTSet1`1

Represents the generic type arguments marker for ISet`1.

DI.Setup("Composition")
                .Bind<IDependency<TTSet1<TT>>>().To<Dependency<TTSet1<TT>>>();
            
TTSet2`1

Represents the generic type arguments marker for ISet`1.

DI.Setup("Composition")
                .Bind<IDependency<TTSet2<TT>>>().To<Dependency<TTSet2<TT>>>();
            
TTSet3`1

Represents the generic type arguments marker for ISet`1.

DI.Setup("Composition")
                .Bind<IDependency<TTSet3<TT>>>().To<Dependency<TTSet3<TT>>>();
            
TTSet4`1

Represents the generic type arguments marker for ISet`1.

DI.Setup("Composition")
                .Bind<IDependency<TTSet4<TT>>>().To<Dependency<TTSet4<TT>>>();
            
TypeAttribute

The injection type can be defined manually using the Type attribute. This attribute explicitly overrides an injected type, otherwise it would be determined automatically based on the type of the constructor/method, property, or field parameter. This attribute is part of the API, but you can use your own attribute at any time, and this allows you to define them in the assembly and namespace you want.

interface IDependency { }
             
            
             class AbcDependency: IDependency { }
            
            
             class XyzDependency: IDependency { }
            
            
             interface IService
             {
                 IDependency Dependency1 { get; }
            
                 IDependency Dependency2 { get; }
             }
            
            
             class Service: IService
             {
                 public Service(
                     [Type(typeof(AbcDependency))] IDependency dependency1,
                     [Type(typeof(XyzDependency))] IDependency dependency2)
                 {
                     Dependency1 = dependency1;
                     Dependency2 = dependency2;
                 }
            
            
                 public IDependency Dependency1 { get; }
            
            
                 public IDependency Dependency2 { get; }
             }
            
            
             DI.Setup("Composition")
                 .Bind<IService>().To<Service>().Root<IService>("Root");
             

See also DependencyAttribute.

See also TagAttribute.

See also OrdinalAttribute.

Constructor TypeAttribute(System.Type)

Creates an attribute instance.

  • parameter type - The injection type. See also Bind1(System.Object[])_ and _Bind1(System.Object[]).

Examples

Basics

Lifetimes

Base Class Library

Generics

Attributes

Interception

Hints

Advanced

Use Cases

Unity

Applications

Generated Code

Each generated class, hereafter called a composition, must be customized. Setup starts with a call to the Setup(string compositionTypeName) method:

DI.Setup("Composition")
    .Bind<IDependency>().To<Dependency>()
    .Bind<IService>().To<Service>()
    .Root<IService>("Root");
The following class will be generated
partial class Composition
{
    // Default constructor
    public Composition() { }

    // Scope constructor
    internal Composition(Composition parentScope) { }

    // Composition root
    public IService Root
    {
        get
        {
            return new Service(new Dependency());
        }
    }

    public T Resolve<T>()  { ... }

    public T Resolve<T>(object? tag)  { ... }

    public object Resolve(Type type) { ... }

    public object Resolve(Type type, object? tag) { ... }
}

The compositionTypeName parameter can be omitted

  • if the setup is performed inside a partial class, then the composition will be created for this partial class
  • for the case of a class with composition kind CompositionKind.Global, see this example
Setup arguments

The first parameter is used to specify the name of the composition class. All sets with the same name will be combined to create one composition class. Alternatively, this name may contain a namespace, e.g. a composition class is generated for Sample.Composition:

namespace Sample
{
    partial class Composition
    {
        ...
    }
}

The second optional parameter may have multiple values to determine the kind of composition.

CompositionKind.Public

This value is used by default. If this value is specified, a normal composition class will be created.

CompositionKind.Internal

If you specify this value, the class will not be generated, but this setup can be used by others as a base setup. For example:

DI.Setup("BaseComposition", CompositionKind.Internal)
    .Bind().To<Dependency>();

DI.Setup("Composition").DependsOn("BaseComposition")
    .Bind().To<Service>();    

If the CompositionKind.Public flag is set in the composition setup, it can also be the base for other compositions, as in the example above.

CompositionKind.Global

No composition class will be created when this value is specified, but this setup is the base setup for all setups in the current project, and DependsOn(...) is not required.

Constructors

Default constructor

It's quite trivial, this constructor simply initializes the internal state.

Parameterized constructor

It replaces the default constructor and is only created if at least one argument is specified. For example:

DI.Setup("Composition")
    .Arg<string>("name")
    .Arg<int>("id")
    ...

In this case, the constructor with arguments is as follows:

public Composition(string name, int id) { ... }

and there is no default constructor. It is important to remember that only those arguments that are used in the object graph will appear in the constructor. Arguments that are not involved cannot be defined, as they are omitted from the constructor parameters to save resources.

Scope constructor

This constructor creates a composition instance for the new scope. This allows Lifetime.Scoped to be applied. See this example for details.

Composition Roots

Regular Composition Roots

To create an object graph quickly and conveniently, a set of properties (or a methods) is formed. These properties/methods are here called roots of compositions. The type of a property/method is the type of the root object created by the composition. Accordingly, each invocation of a property/method leads to the creation of a composition with a root element of this type.

DI.Setup("Composition")
    .Bind<IService>().To<Service>()
    .Root<IService>("MyService");

var composition = new Composition();
var service = composition.MyService;
service = composition.Resolve<IService>();
service = composition.Resolve(typeof(IService));

In this case, the property for the IService type will be named MyService and will be available for direct use. The result of its use will be the creation of a composition of objects with the root of IService type:

public IService MyService
{
    get
    { 
        ...
        return new Service(...);
    }
}

This is recommended way to create a composition root. A composition class can contain any number of roots.

In addition, the composition roots can be resolved using the Resolve() methods:

service = composition.Resolve<IService>();
service = composition.Resolve(typeof(IService));

![TIP]

  • There is no limit to the number of roots, but you should consider limiting the number of roots. Ideally, an application should have a single composition root
  • The name of the composition root is arbitrarily chosen depending on its purpose, but should be restricted by the property naming conventions in C# since it is the same name as a property in the composition class
  • It is recommended that composition roots be resolved using normal properties or methods instead of methods of type Resolve().

Anonymous Composition Roots

If the root name is empty, an anonymous composition root with a random name is created:

private IService RootM07D16di_0001
{
    get { ... }
}

These properties (or methods) have an arbitrary name and access modifier private and cannot be used directly from the code. Do not attempt to use them, as their names are arbitrarily changed. Anonymous composition roots can be resolved by Resolve methods:

DI.Setup("Composition")
    .Bind<IService>().To<Service>()
    .Root<IService>();

var composition = new Composition();
var service = composition.Resolve<IService>();
service = composition.Resolve(typeof(IService));
Methods "Resolve"

Methods "Resolve"

By default, a set of four Resolve methods is generated:

public T Resolve<T>() { ... }

public T Resolve<T>(object? tag) { ... }

public object Resolve(Type type) { ... }

public object Resolve(Type type, object? tag) { ... }

These methods can resolve both public and anonymous composition roots that do not depend on any arguments of the composition roots. They are useful when using the Service Locator approach, where the code resolves composition roots in place:

var composition = new Composition();

composition.Resolve<IService>();

This is a not recommended way to create composition roots because Resolve methods have a number of disadvantages:

  • They provide access to an unlimited set of dependencies.
  • Their use can potentially lead to runtime exceptions, for example, when the corresponding root has not been defined.
  • Lead to performance degradation because they search for the root of a composition based on its type.

To control the generation of these methods, see the Resolve hint.

Dispose and DisposeAsync

Provides a mechanism to release unmanaged resources. These methods are generated only if the composition contains at least one singleton/scoped instance that implements either the IDisposable and/or DisposeAsync interface. The Dispose() or DisposeAsync() method of the composition should be called to dispose of all created singleton/scoped objects:

using var composition = new Composition();

or

await using var composition = new Composition();

To dispose objects of other lifetimes please see this or this examples.

Setup hints

Setup hints

Hints are used to fine-tune code generation. Setup hints can be used as shown in the following example:

DI.Setup("Composition")
    .Hint(Hint.Resolve, "Off")
    .Hint(Hint.ThreadSafe, "Off")
    .Hint(Hint.ToString, "On")
    ...

In addition, setup hints can be commented out before the Setup method as hint = value. For example:

// Resolve = Off
// ThreadSafe = Off
DI.Setup("Composition")
    ...

Both approaches can be mixed:

// Resolve = Off
DI.Setup("Composition")
    .Hint(Hint.ThreadSafe, "Off")
    ...
Hint Values C# version Default
Resolve On or Off On
OnNewInstance On or Off 9.0 Off
OnNewInstancePartial On or Off On
OnNewInstanceImplementationTypeNameRegularExpression Regular expression .+
OnNewInstanceImplementationTypeNameWildcard Wildcard *
OnNewInstanceTagRegularExpression Regular expression .+
OnNewInstanceTagWildcard Wildcard *
OnNewInstanceLifetimeRegularExpression Regular expression .+
OnNewInstanceLifetimeWildcard Wildcard *
OnDependencyInjection On or Off 9.0 Off
OnDependencyInjectionPartial On or Off On
OnDependencyInjectionImplementationTypeNameRegularExpression Regular expression .+
OnDependencyInjectionImplementationTypeNameWildcard Wildcard *
OnDependencyInjectionContractTypeNameRegularExpression Regular expression .+
OnDependencyInjectionContractTypeNameWildcard Wildcard *
OnDependencyInjectionTagRegularExpression Regular expression .+
OnDependencyInjectionTagWildcard Wildcard *
OnDependencyInjectionLifetimeRegularExpression Regular expression .+
OnDependencyInjectionLifetimeWildcard Wildcard *
OnCannotResolve On or Off 9.0 Off
OnCannotResolvePartial On or Off On
OnCannotResolveContractTypeNameRegularExpression Regular expression .+
OnCannotResolveContractTypeNameWildcard Wildcard *
OnCannotResolveTagRegularExpression Regular expression .+
OnCannotResolveTagWildcard Wildcard *
OnCannotResolveLifetimeRegularExpression Regular expression .+
OnCannotResolveLifetimeWildcard Wildcard *
OnNewRoot On or Off Off
OnNewRootPartial On or Off On
ToString On or Off Off
ThreadSafe On or Off On
ResolveMethodModifiers Method modifier public
ResolveMethodName Method name Resolve
ResolveByTagMethodModifiers Method modifier public
ResolveByTagMethodName Method name Resolve
ObjectResolveMethodModifiers Method modifier public
ObjectResolveMethodName Method name Resolve
ObjectResolveByTagMethodModifiers Method modifier public
ObjectResolveByTagMethodName Method name Resolve
DisposeMethodModifiers Method modifier public
DisposeAsyncMethodModifiers Method modifier public
FormatCode On or Off Off
SeverityOfNotImplementedContract Error or Warning or Info or Hidden Error
Comments On or Off On
SkipDefaultConstructor On or Off Off
SkipDefaultConstructorImplementationTypeNameRegularExpression Regular expression .+
SkipDefaultConstructorImplementationTypeNameWildcard Wildcard *
SkipDefaultConstructorLifetimeRegularExpression Regular expression .+
SkipDefaultConstructorLifetimeWildcard Wildcard *
DisableAutoBinding On or Off Off
DisableAutoBindingImplementationTypeNameRegularExpression Regular expression .+
DisableAutoBindingImplementationTypeNameWildcard Wildcard *
DisableAutoBindingLifetimeRegularExpression Regular expression .+
DisableAutoBindingLifetimeWildcard Wildcard *

The list of hints will be gradually expanded to meet the needs and desires for fine-tuning code generation. Please feel free to add your ideas.

Resolve Hint

Determines whether to generate Resolve methods. By default, a set of four Resolve methods are generated. Set this hint to Off to disable the generation of resolve methods. This will reduce the generation time of the class composition, and in this case no anonymous composition roots will be generated. The class composition will be smaller and will only have public roots. When the Resolve hint is disabled, only the public roots properties are available, so be sure to explicitly define them using the Root<T>(string name) method with an explicit composition root name.

OnNewInstance Hint

Determines whether to use the OnNewInstance partial method. By default, this partial method is not generated. This can be useful, for example, for logging purposes:

internal partial class Composition
{
    partial void OnNewInstance<T>(ref T value, object? tag, object lifetime) =>
        Console.WriteLine($"'{typeof(T)}'('{tag}') created.");
}

You can also replace the created instance with a T type, where T is the actual type of the created instance. To minimize performance loss when calling OnNewInstance, use the three hints below.

OnNewInstancePartial Hint

Determines whether to generate the OnNewInstance partial method. By default, this partial method is generated when the OnNewInstance hint is On.

OnNewInstanceImplementationTypeNameRegularExpression Hint

This is a regular expression for filtering by instance type name. This hint is useful when OnNewInstance is in On state and it is necessary to limit the set of types for which the OnNewInstance method will be called.

OnNewInstanceImplementationTypeNameWildcard Hint

This is a Wildcard for filtering by instance type name. This hint is useful when OnNewInstance is in On state and it is necessary to limit the set of types for which the OnNewInstance method will be called.

OnNewInstanceTagRegularExpression Hint

This is a regular expression for filtering by tag. This hint is also useful when OnNewInstance is in On state and it is necessary to limit the set of tags for which the OnNewInstance method will be called.

OnNewInstanceTagWildcard Hint

This is a wildcard for filtering by tag. This hint is also useful when OnNewInstance is in On state and it is necessary to limit the set of tags for which the OnNewInstance method will be called.

OnNewInstanceLifetimeRegularExpression Hint

This is a regular expression for filtering by lifetime. This hint is also useful when OnNewInstance is in On state and it is necessary to restrict the set of life times for which the OnNewInstance method will be called.

OnNewInstanceLifetimeWildcard Hint

This is a wildcard for filtering by lifetime. This hint is also useful when OnNewInstance is in On state and it is necessary to restrict the set of life times for which the OnNewInstance method will be called.

OnDependencyInjection Hint

Determines whether to use the OnDependencyInjection partial method when the OnDependencyInjection hint is On to control dependency injection. By default it is On.

// OnDependencyInjection = On
// OnDependencyInjectionPartial = Off
// OnDependencyInjectionContractTypeNameRegularExpression = ICalculator[\d]{1}
// OnDependencyInjectionTagRegularExpression = Abc
DI.Setup("Composition")
    ...

OnDependencyInjectionPartial Hint

Determines whether to generate the OnDependencyInjection partial method to control dependency injection. By default, this partial method is not generated. It cannot have an empty body because of the return value. It must be overridden when it is generated. This may be useful, for example, for Interception Scenario.

// OnDependencyInjection = On
// OnDependencyInjectionContractTypeNameRegularExpression = ICalculator[\d]{1}
// OnDependencyInjectionTagRegularExpression = Abc
DI.Setup("Composition")
    ...

To minimize performance loss when calling OnDependencyInjection, use the three tips below.

OnDependencyInjectionImplementationTypeNameRegularExpression Hint

This is a regular expression for filtering by instance type name. This hint is useful when OnDependencyInjection is in On state and it is necessary to restrict the set of types for which the OnDependencyInjection method will be called.

OnDependencyInjectionImplementationTypeNameWildcard Hint

This is a wildcard for filtering by instance type name. This hint is useful when OnDependencyInjection is in On state and it is necessary to restrict the set of types for which the OnDependencyInjection method will be called.

OnDependencyInjectionContractTypeNameRegularExpression Hint

This is a regular expression for filtering by the name of the resolving type. This hint is also useful when OnDependencyInjection is in On state and it is necessary to limit the set of permissive types for which the OnDependencyInjection method will be called.

OnDependencyInjectionContractTypeNameWildcard Hint

This is a wildcard for filtering by the name of the resolving type. This hint is also useful when OnDependencyInjection is in On state and it is necessary to limit the set of permissive types for which the OnDependencyInjection method will be called.

OnDependencyInjectionTagRegularExpression Hint

This is a regular expression for filtering by tag. This hint is also useful when OnDependencyInjection is in the On state and you want to limit the set of tags for which the OnDependencyInjection method will be called.

OnDependencyInjectionTagWildcard Hint

This is a wildcard for filtering by tag. This hint is also useful when OnDependencyInjection is in the On state and you want to limit the set of tags for which the OnDependencyInjection method will be called.

OnDependencyInjectionLifetimeRegularExpression Hint

This is a regular expression for filtering by lifetime. This hint is also useful when OnDependencyInjection is in On state and it is necessary to restrict the set of lifetime for which the OnDependencyInjection method will be called.

OnDependencyInjectionLifetimeWildcard Hint

This is a wildcard for filtering by lifetime. This hint is also useful when OnDependencyInjection is in On state and it is necessary to restrict the set of lifetime for which the OnDependencyInjection method will be called.

OnCannotResolve Hint

Determines whether to use the OnCannotResolve<T>(...) partial method to handle a scenario in which an instance cannot be resolved. By default, this partial method is not generated. Because of the return value, it cannot have an empty body and must be overridden at creation.

// OnCannotResolve = On
// OnCannotResolveContractTypeNameRegularExpression = string|DateTime
// OnDependencyInjectionTagRegularExpression = null
DI.Setup("Composition")
    ...

To avoid missing failed bindings by mistake, use the two relevant hints below.

OnCannotResolvePartial Hint

Determines whether to generate the OnCannotResolve<T>(...) partial method when the OnCannotResolve hint is On to handle a scenario in which an instance cannot be resolved. By default it is On.

// OnCannotResolve = On
// OnCannotResolvePartial = Off
// OnCannotResolveContractTypeNameRegularExpression = string|DateTime
// OnDependencyInjectionTagRegularExpression = null
DI.Setup("Composition")
    ...

To avoid missing failed bindings by mistake, use the two relevant hints below.

OnNewRoot Hint

Determines whether to use a static partial method OnNewRoot<TContract, T>(...) to handle the new composition root registration event.

// OnNewRoot = On
DI.Setup("Composition")
    ...

Be careful, this hint disables checks for the ability to resolve dependencies!

OnNewRootPartial Hint

Determines whether to generate a static partial method OnNewRoot<TContract, T>(...) when the OnNewRoot hint is On to handle the new composition root registration event.

// OnNewRootPartial = Off
DI.Setup("Composition")
    ...

OnCannotResolveContractTypeNameRegularExpression Hint

This is a regular expression for filtering by the name of the resolving type. This hint is also useful when OnCannotResolve is in On state and it is necessary to limit the set of resolving types for which the OnCannotResolve method will be called.

OnCannotResolveContractTypeNameWildcard Hint

This is a wildcard for filtering by the name of the resolving type. This hint is also useful when OnCannotResolve is in On state and it is necessary to limit the set of resolving types for which the OnCannotResolve method will be called.

OnCannotResolveTagRegularExpression Hint

This is a regular expression for filtering by tag. This hint is also useful when OnCannotResolve is in On state and it is necessary to limit the set of tags for which the OnCannotResolve method will be called.

OnCannotResolveTagWildcard Hint

This is a wildcard for filtering by tag. This hint is also useful when OnCannotResolve is in On state and it is necessary to limit the set of tags for which the OnCannotResolve method will be called.

OnCannotResolveLifetimeRegularExpression Hint

This is a regular expression for filtering by lifetime. This hint is also useful when OnCannotResolve is in the On state and it is necessary to restrict the set of lives for which the OnCannotResolve method will be called.

OnCannotResolveLifetimeWildcard Hint

This is a wildcard for filtering by lifetime. This hint is also useful when OnCannotResolve is in the On state and it is necessary to restrict the set of lives for which the OnCannotResolve method will be called.

ToString Hint

Determines whether to generate the ToString() method. This method provides a class diagram in mermaid format. To see this diagram, just call the ToString method and copy the text to this site.

// ToString = On
DI.Setup("Composition")
    .Bind<IService>().To<Service>()
    .Root<IService>("MyService");
    
var composition = new Composition();
string classDiagram = composition.ToString(); 

ThreadSafe Hint

This hint determines whether the composition of objects will be created in a thread-safe way. The default value of this hint is On. It is a good practice not to use threads when creating an object graph, in this case the hint can be disabled, which will result in a small performance gain. For example:

// ThreadSafe = Off
DI.Setup("Composition")
    .Bind<IService>().To<Service>()
    .Root<IService>("MyService");

ResolveMethodModifiers Hint

Overrides the modifiers of the public T Resolve<T>() method.

ResolveMethodName Hint

Overrides the method name for public T Resolve<T>().

ResolveByTagMethodModifiers Hint

Overrides the modifiers of the public T Resolve<T>(object? tag) method.

ResolveByTagMethodName Hint

Overrides the method name for public T Resolve<T>(object? tag).

ObjectResolveMethodModifiers Hint

Overrides the modifiers of the public object Resolve(Type type) method.

ObjectResolveMethodName Hint

Overrides the method name for public object Resolve(Type type).

ObjectResolveByTagMethodModifiers Hint

Overrides the modifiers of the public object Resolve(Type type, object? tag) method.

ObjectResolveByTagMethodName Hint

Overrides the method name for public object Resolve(Type type, object? tag).

DisposeMethodModifiers Hint

Overrides the modifiers of the public void Dispose() method.

DisposeAsyncMethodModifiers Hint

Overrides the modifiers of the public ValueTask DisposeAsync() method.

FormatCode Hint

Specifies whether the generated code should be formatted. This option consumes a lot of CPU resources. This hint may be useful when studying the generated code or, for example, when making presentations.

SeverityOfNotImplementedContract Hint

Indicates the severity level of the situation when, in the binding, an implementation does not implement a contract. Possible values:

  • "Error", it is default value.
  • "Warning" - something suspicious but allowed.
  • "Info" - information that does not indicate a problem.
  • "Hidden" - what's not a problem.

Comments Hint

Specifies whether the generated code should be commented.

// Represents the composition class
DI.Setup(nameof(Composition))
    .Bind<IService>().To<Service>()
    // Provides a composition root of my service
    .Root<IService>("MyService");

Appropriate comments will be added to the generated Composition class and the documentation for the class, depending on the IDE used, will look something like this:

SystemThreadingLock Hint

Indicates whether System.Threading.Lock should be used whenever possible instead of the classic approach of synchronizing object access using System.Threading.Monitor1. On` by default.

DI.Setup(nameof(Composition))
    .Hint(Hint.SystemThreadingLock, "Off")
    .Bind().To<Service>()
    .Root<Service>("MyService");

ReadmeDocumentation1.png

Then documentation for the composition root:

ReadmeDocumentation2.png

Code generation workflow
flowchart TD
    start@{ shape: circle, label: "Start" }
    setups[fa:fa-search DI setups analysis]
    types["`fa:fa-search Types analysis
    constructors/methods/properties/fields`"] 
    subgraph dep[Dependency graph]
    option[fa:fa-search Selecting a next dependency set]
    creating[fa:fa-cog Creating a dependency graph variant]
    verification{fa:fa-check-circle Verification}
    end
    codeGeneration[fa:fa-code Code generation]
    compilation[fa:fa-cog Compilation]
    failed@{ shape: dbl-circ, label: "fa:fa-thumbs-down Compilation failed" }
    success@{ shape: dbl-circ, label: "fa:fa-thumbs-up Success" }

    start ==> setups
    setups -.->|Has problems| failed
    setups ==> types
    types -.-> |Has problems| failed
    types ==> option
    option ==> creating
    option -.-> |There are no other options| failed
    creating ==> verification
    verification -->|Has problems| option
    verification ==>|Correct| codeGeneration
    codeGeneration ==> compilation
    compilation -.-> |Has problems| failed
    compilation ==> success
Loading

Project template

Install the DI template Pure.DI.Templates

dotnet new install Pure.DI.Templates

Create a "Sample" console application from the template di

dotnet new di -o ./Sample

And run it

dotnet run --project Sample

For more information about the template, please see this page.

Troubleshooting

Version update

When updating the version, it is possible that the previous version of the code generator remains active and is used by compilation services. In this case, the old and new versions of the generator may conflict. For a project where the code generator is used, it is recommended to do the following:

  • After updating the version, close the IDE if it is open
  • Delete the obj and bin directories
  • Execute the following commands one by one
dotnet build-server shutdown
dotnet restore
dotnet build
Disabling API generation

Pure.DI automatically generates its API. If an assembly already has the Pure.DI API, for example, from another assembly, it is sometimes necessary to disable its automatic generation to avoid ambiguity. To do this, you need to add a DefineConstants element to the project files of these modules. For example:

<PropertyGroup>
    <DefineConstants>$(DefineConstants);PUREDI_API_SUPPRESSION</DefineConstants>
</PropertyGroup>
Display generated files

You can set project properties to save generated files and control their storage location. In the project file, add the <EmitCompilerGeneratedFiles> element to the <PropertyGroup> group and set its value to true. Build the project again. The generated files are now created in the obj/Debug/netX.X/generated/Pure.DI/Pure.DI/Pure.DI.SourceGenerator directory. The path components correspond to the build configuration, the target framework, the source generator project name, and the full name of the generator type. You can choose a more convenient output folder by adding the <CompilerGeneratedFilesOutputPath> element to the application project file. For example:

<Project Sdk="Microsoft.NET.Sdk">
    
    <PropertyGroup>
        <EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
        <CompilerGeneratedFilesOutputPath>$(BaseIntermediateOutputPath)Generated</CompilerGeneratedFilesOutputPath>
    </PropertyGroup>
    
</Project>
Performance profiling

Please install the JetBrains.dotTrace.GlobalTools dotnet tool globally, for example:

dotnet tool install --global JetBrains.dotTrace.GlobalTools --version 2024.3.3

Or make sure it is installed. Add the following sections to the project:

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <PureDIProfilePath>c:\profiling</PureDIProfilePath>
  </PropertyGroup>

  <ItemGroup>
    <CompilerVisibleProperty Include="PureDIProfilePath" />
  </ItemGroup>

</Project>

Replace the path like c:\profiling with the path where the profiling results will be saved.

Start the project build and wait until a file like c:\profiling\pure_di_????.dtt appears in the directory.

Additional resources

Examples of how to set up a composition

Articles

RU DotNext video

DotNext Pure.DI

AI Context

Contextual AI needs to understand the situation it’s in. This means knowing details like API, usage scenarios, etc. This helps the AI give more relevant and personalized responses. So Markdown docs below can be useful if you or your team rely on an AI assistant to write code using Pure.DI:

AI Context file Size Tokens
AI_CONTEXT_SMALL.md 28KB 7K
AI_CONTEXT_MEDIUM.md 123KB 31K
AI_CONTEXT_LARGE.md 410KB 105K

How to contribute to Pure.DI

Thank you for your interest in contributing to the Pure.DI project! First of all, if you are going to make a big change or feature, please open a problem first. That way, we can coordinate and understand if the change you're going to work on fits with current priorities and if we can commit to reviewing and merging it within a reasonable timeframe. We don't want you to waste a lot of your valuable time on something that may not align with what we want for Pure.DI.

Contribution prerequisites: .NET SDK 9.0 or later is installed.

This repository contains the following directories and files:

πŸ“ .github                       GitHub related files and main.yml for building using GitGub actions
πŸ“ .logs                         temporary files for generating the README.md file
πŸ“ .run                          configuration files for the Rider IDE
πŸ“ benchmarks                    projects for performance measurement
πŸ“ build                         application for building locally and using CI/CD
πŸ“ docs                          resources for the README.md file
πŸ“ readme                        sample scripts and examples of application implementations
πŸ“ samples                       sample projects
πŸ“ src                           source codes of the code generator and all libraries
|- πŸ“‚ Pure.DI                    source code generator project
|- πŸ“‚ Pure.DI.Abstractions       abstraction library for Pure.DI
|- πŸ“‚ Pure.DI.Core               basic implementation of the source code generator
|- πŸ“‚ Pure.DI.MS                 project for integration with Microsoft DI
|- πŸ“‚ Pure.DI.Templates          project templates for creating .NET projects using Pure.DI
|- πŸ“„ Directory.Build.props      common MSBUILD properties for all source code generator projects
|- πŸ“„ Library.props              common MSBUILD properties for library projects such as Pure.DI.Abstractions
πŸ“ tests                         contains projects for testing
|- πŸ“‚ Pure.DI.Example            project for testing some integration scenarios
|- πŸ“‚ Pure.DI.IntegrationTests   integration tests
|- πŸ“‚ Pure.DI.Tests              unit tests for basic functionality
|- πŸ“‚ Pure.DI.UsageTests         usage tests, used for examples in README.md
|- πŸ“„ Directory.Build.props      common MSBUILD properties for all test projects
πŸ“„ LICENSE                       license file
πŸ“„ build.cmd                     Windows script file to run one of the build steps, see description below
πŸ“„ build.sh                      Linux/Mac OS script file to run one of the build steps, see description below
πŸ“„ .space.kts                    build file using JetBrains space actions
πŸ“„ README.md                     this README.md file
πŸ“„ SECURITY.md                   policy file for handling security bugs and vulnerabilities
πŸ“„ Directory.Build.props         basic MSBUILD properties for all projects
πŸ“„ Pure.DI.sln                   .NET solution file

The entire build logic is a regular console .NET application. You can use the build.cmd and build.sh files with the appropriate command in the parameters to perform all basic actions on the project, e.g:

Commands Description
ai Generate AI context
bm, benchmarks Run benchmarks
c, check Compatibility checks
dp, deploy Package deployment
e, example Create examples
g, generator Build and test the source code generator
i, install Install templates
l, libs Build and test libraries
p, pack Create NuGet packages
perf, performance Performance tests
pb, publish Publish the balazor web sssembly example
r, readme Generate README.md
t, template Create and deploy templates
te, testexamples Test examples
u, upgrade Upgrading the internal version of DI to the latest public version

For example, to build and test the source code generator:

./build.sh generator

or to run benchmarks:

./build.cmd benchmarks

If you are using the Rider IDE, it already has a set of configurations to run these commands. This project uses C# interactive build automation system for .NET. This tool helps to make .NET builds more efficient.

State of build

Tests Examples Performance
Tests Examples Performance

Thanks!

Benchmarks

Array
Method Mean ErrorStdDevRatioRatioSDGen0Gen1AllocatedAlloc Ratio
'Pure.DI composition root'198.9 ns4.01 ns7.44 ns0.970.050.0365-632 B1.00
'Hand Coded'205.2 ns4.15 ns7.80 ns1.000.050.0365-632 B1.00
'Pure.DI Resolve(Type)'213.2 ns4.22 ns6.70 ns1.040.050.0365-632 B1.00
'Pure.DI Resolve<T>()'218.9 ns4.33 ns6.07 ns1.070.050.0365-632 B1.00
LightInject222.2 ns4.42 ns4.14 ns1.080.050.0365-632 B1.00
DryIoc226.1 ns4.54 ns5.90 ns1.100.050.0365-632 B1.00
Unity8,851.1 ns89.93 ns75.10 ns43.201.680.8392-14520 B22.97
Autofac37,847.0 ns3,830.79 ns11,235.04 ns184.7255.051.67850.061028976 B45.85

Array details

Enum
Method Mean ErrorStdDevRatioRatioSDGen0Gen1AllocatedAlloc Ratio
'Pure.DI Resolve<T>()'153.2 ns3.09 ns4.23 ns0.970.040.0198-344 B1.00
'Pure.DI Resolve(Type)'155.5 ns3.16 ns3.51 ns0.980.030.0198-344 B1.00
'Pure.DI composition root'157.2 ns3.03 ns4.45 ns0.990.040.0198-344 B1.00
'Hand Coded'158.2 ns3.15 ns4.21 ns1.000.040.0198-344 B1.00
'Microsoft DI'207.5 ns4.19 ns3.92 ns1.310.040.0272-472 B1.37
LightInject322.5 ns6.48 ns10.27 ns2.040.080.0496-856 B2.49
DryIoc328.0 ns6.51 ns10.51 ns2.070.090.0496-856 B2.49
Unity7,302.2 ns140.67 ns172.76 ns46.201.620.7935-13752 B39.98
Autofac26,766.0 ns239.86 ns200.30 ns169.344.651.67850.061029104 B84.60

Enum details

Func
Method Mean ErrorStdDevRatioRatioSDGen0AllocatedAlloc Ratio
'Pure.DI composition root'10.88 ns0.095 ns0.084 ns0.940.010.001424 B1.00
'Hand Coded'11.54 ns0.166 ns0.155 ns1.000.020.001424 B1.00
'Pure.DI Resolve<T>()'14.76 ns0.104 ns0.098 ns1.280.020.001424 B1.00
'Pure.DI Resolve(Type)'15.49 ns0.109 ns0.097 ns1.340.020.001424 B1.00
DryIoc67.73 ns1.351 ns1.387 ns5.870.140.0069120 B5.00
LightInject326.89 ns5.239 ns4.644 ns28.330.540.0291504 B21.00
Unity3,686.49 ns20.737 ns18.383 ns319.544.450.14502552 B106.33
Autofac10,830.28 ns128.605 ns114.005 ns938.7415.550.808714008 B583.67

Func details

Singleton
Method Mean Error StdDevRatioRatioSDGen0Gen1AllocatedAlloc Ratio
'Hand Coded'10.47 ns0.133 ns0.124 ns1.000.020.0014-24 B1.00
'Pure.DI composition root'11.12 ns0.304 ns0.338 ns1.060.030.0014-24 B1.00
'Pure.DI Resolve<T>()'13.07 ns0.345 ns0.369 ns1.250.040.0014-24 B1.00
'Pure.DI Resolve(Type)'13.46 ns0.297 ns0.278 ns1.290.030.0014-24 B1.00
DryIoc27.57 ns0.152 ns0.127 ns2.630.030.0014-24 B1.00
'Simple Injector'38.33 ns0.151 ns0.126 ns3.660.040.0014-24 B1.00
'Microsoft DI'39.94 ns0.301 ns0.267 ns3.820.050.0014-24 B1.00
LightInject887.91 ns3.402 ns3.016 ns84.841.010.0010-24 B1.00
Unity5,962.55 ns28.551 ns25.310 ns569.746.950.1831-3184 B132.67
Autofac19,999.91 ns158.901 ns140.862 ns1,911.0725.521.37330.030524208 B1,008.67
'Castle Windsor'30,901.04 ns108.855 ns90.899 ns2,952.7134.951.3428-23912 B996.33
Ninject117,479.34 ns2,330.050 ns2,589.845 ns11,225.60273.584.15041.098673176 B3,049.00

Singleton details

Transient
Method Mean Error StdDevRatioRatioSDGen0Gen1AllocatedAlloc Ratio
'Pure.DI composition root'10.32 ns0.115 ns0.108 ns0.940.010.0014-24 B1.00
'Hand Coded'10.97 ns0.127 ns0.119 ns1.000.010.0014-24 B1.00
'Pure.DI Resolve<T>()'13.00 ns0.098 ns0.091 ns1.180.010.0014-24 B1.00
'Pure.DI Resolve(Type)'14.57 ns0.178 ns0.167 ns1.330.020.0014-24 B1.00
LightInject20.18 ns0.154 ns0.137 ns1.840.020.0014-24 B1.00
'Microsoft DI'26.82 ns0.098 ns0.082 ns2.440.030.0014-24 B1.00
DryIoc26.87 ns0.141 ns0.118 ns2.450.030.0014-24 B1.00
'Simple Injector'37.33 ns0.213 ns0.178 ns3.400.040.0014-24 B1.00
Unity9,258.36 ns37.403 ns33.157 ns843.689.300.2899-5176 B215.67
Autofac29,574.31 ns259.556 ns230.089 ns2,694.9934.731.92260.091633224 B1,384.33
'Castle Windsor'58,089.75 ns113.928 ns95.135 ns5,293.5056.043.1128-54360 B2,265.00
Ninject266,156.53 ns5,315.749 ns7,451.939 ns24,253.83713.797.32421.9531128736 B5,364.00

Transient details

Benchmarks environment

BenchmarkDotNet v0.15.0, Linux Ubuntu 22.04.5 LTS (Jammy Jellyfish) (container)
Intel Xeon Platinum 8175M CPU 2.50GHz, 1 CPU, 2 logical cores and 1 physical core
.NET SDK 9.0.102
  [Host]     : .NET 9.0.1 (9.0.124.61010), X64 RyuJIT AVX-512F+CD+BW+DQ+VL
  DefaultJob : .NET 9.0.1 (9.0.124.61010), X64 RyuJIT AVX-512F+CD+BW+DQ+VL