Skip to content

Latest commit

 

History

History
182 lines (155 loc) · 3.94 KB

File metadata and controls

182 lines (155 loc) · 3.94 KB

Func

Func helps when the logic must enter instances of some type on demand or more than once. This is a very handy mechanism for instance replication. For example it is used when implementing the Lazy<T> injection.

using Shouldly;
using Pure.DI;
using System.Collections.Immutable;

DI.Setup(nameof(Composition))
    .Bind().As(Lifetime.Singleton).To<TicketIdGenerator>()
    .Bind().To<Ticket>()
    .Bind().To<QueueTerminal>()

    // Composition root
    .Root<IQueueTerminal>("Terminal");

var composition = new Composition();
var terminal = composition.Terminal;

terminal.Tickets.Length.ShouldBe(3);

terminal.Tickets[0].Id.ShouldBe(1);
terminal.Tickets[1].Id.ShouldBe(2);
terminal.Tickets[2].Id.ShouldBe(3);

interface ITicketIdGenerator
{
    int NextId { get; }
}

class TicketIdGenerator : ITicketIdGenerator
{
    public int NextId => ++field;
}

interface ITicket
{
    int Id { get; }
}

class Ticket(ITicketIdGenerator idGenerator) : ITicket
{
    public int Id { get; } = idGenerator.NextId;
}

interface IQueueTerminal
{
    ImmutableArray<ITicket> Tickets { get; }
}

class QueueTerminal(Func<ITicket> ticketFactory) : IQueueTerminal
{
    public ImmutableArray<ITicket> Tickets { get; } =
    [
        // The factory creates a new instance of the ticket each time it is called
        ticketFactory(),
        ticketFactory(),
        ticketFactory()
    ];
}
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

Be careful, replication takes into account the lifetime of the object.

The following partial class will be generated:

partial class Composition
{
#if NET9_0_OR_GREATER
  private readonly Lock _lock = new Lock();
#else
  private readonly Object _lock = new Object();
#endif

  private TicketIdGenerator? _singletonTicketIdGenerator62;

  public IQueueTerminal Terminal
  {
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    get
    {
      Func<ITicket> perBlockFunc400 = new Func<ITicket>(
      [MethodImpl(MethodImplOptions.AggressiveInlining)]
      () =>
      {
        if (_singletonTicketIdGenerator62 is null)
          lock (_lock)
            if (_singletonTicketIdGenerator62 is null)
            {
              _singletonTicketIdGenerator62 = new TicketIdGenerator();
            }

        return new Ticket(_singletonTicketIdGenerator62);
      });
      return new QueueTerminal(perBlockFunc400);
    }
  }
}

Class diagram:

---
 config:
  maxTextSize: 2147483647
  maxEdges: 2147483647
  class:
   hideEmptyMembersBox: true
---
classDiagram
	TicketIdGenerator --|> ITicketIdGenerator
	Ticket --|> ITicket
	QueueTerminal --|> IQueueTerminal
	Composition ..> QueueTerminal : IQueueTerminal Terminal
	Ticket o-- "Singleton" TicketIdGenerator : ITicketIdGenerator
	QueueTerminal o-- "PerBlock" FuncᐸITicketᐳ : FuncᐸITicketᐳ
	FuncᐸITicketᐳ *--  Ticket : ITicket
	namespace Pure.DI.UsageTests.BCL.FuncScenario {
		class Composition {
		<<partial>>
		+IQueueTerminal Terminal
		}
		class IQueueTerminal {
			<<interface>>
		}
		class ITicket {
			<<interface>>
		}
		class ITicketIdGenerator {
			<<interface>>
		}
		class QueueTerminal {
				<<class>>
			+QueueTerminal(FuncᐸITicketᐳ ticketFactory)
		}
		class Ticket {
				<<class>>
			+Ticket(ITicketIdGenerator idGenerator)
		}
		class TicketIdGenerator {
				<<class>>
			+TicketIdGenerator()
		}
	}
	namespace System {
		class FuncᐸITicketᐳ {
				<<delegate>>
		}
	}
Loading