Skip to content

Latest commit

 

History

History
124 lines (99 loc) · 3.09 KB

bind-type-attributes.md

File metadata and controls

124 lines (99 loc) · 3.09 KB

Bind type attributes

Shows how several Type attributes can expose one implementation through several contracts. The implementation declares every abstraction it implements once, and each abstraction can be injected on its own.

using Shouldly;
using Pure.DI;

DI.Setup(nameof(Composition))

    // Composition roots
    .Root<IMessageWriter>("Writer")
    .Root<IDiagnosticsSink>("Diagnostics");

var composition = new Composition();

composition.Writer.ShouldBeOfType<ConsoleChannel>();
composition.Diagnostics.ShouldBeOfType<ConsoleChannel>();

interface IMessageWriter;

interface IDiagnosticsSink;

[Type(typeof(IMessageWriter))]
[Type(typeof(IDiagnosticsSink))]
class ConsoleChannel : IMessageWriter, IDiagnosticsSink;
Running this code sample locally
dotnet --list-sdk
  • Create a net10.0 (or later) console application
dotnet new console -n Sample
dotnet add package Pure.DI
dotnet add package Shouldly
  • Copy the example code into the Program.cs file

You are ready to run the example 🚀

dotnet run

Note

Multiple type attributes in the same square-bracket binding group are merged into one binding with several contracts.

This is the attribute spelling of .Bind<IOne>().Bind<ITwo>().To<T>(), and it removes repeated chains from the setup. The composition only keeps roots for the contracts that outside code consumes. Because the contracts share one group, adding a contract changes the same binding and the same instance is reused across the abstractions. A separate group would create a second binding of the same type, so a collection would receive two entries where one was intended.

Tip

Prefer this when the implementation assembly owns its contracts, and the setup API when the choice belongs to one application.

The following partial class will be generated
partial class Composition
{
  public IDiagnosticsSink Diagnostics
  {
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    get
    {
      return new ConsoleChannel();
    }
  }

  public IMessageWriter Writer
  {
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    get
    {
      return new ConsoleChannel();
    }
  }
}

Class diagram:

---
 config:
  class:
   hideEmptyMembersBox: true
---
classDiagram
	ConsoleChannel --|> IDiagnosticsSink
	Composition ..> ConsoleChannel : IDiagnosticsSink Diagnostics
	Composition ..> ConsoleChannel : IMessageWriter Writer
	namespace Pure.DI.UsageTests.Attributes.MultipleBindTypeAttributesScenario {
		class Composition {
		<<partial>>
		+IDiagnosticsSink Diagnostics
		+IMessageWriter Writer
		}
		class ConsoleChannel {
				<<class>>
			+ConsoleChannel()
		}
		class IDiagnosticsSink {
			<<interface>>
		}
	}
Loading

See also: