Skip to content

Latest commit

 

History

History
159 lines (135 loc) · 3.93 KB

File metadata and controls

159 lines (135 loc) · 3.93 KB

Simplified factory

This example shows a simplified manual factory. Each lambda parameter represents an injected dependency, and starting with C# 10 you can add Tag(...) to specify a tagged dependency.

using Shouldly;
using Pure.DI;

DI.Setup(nameof(Composition))
    .Bind("today").To(() => DateTime.Today)
    // Injects FileLogger and DateTime
    // and applies additional initialization logic
    .Bind<IFileLogger>().To((
        FileLogger logger,
        [Tag("today")] DateTime date) => {
        logger.Init($"app-{date:yyyy-MM-dd}.log");
        return logger;
    })
    .Bind().To<OrderProcessingService>()

    // Composition root
    .Root<IOrderProcessingService>("OrderService");

var composition = new Composition();
var service = composition.OrderService;

service.Logger.FileName.ShouldBe($"app-{DateTime.Today:yyyy-MM-dd}.log");

interface IFileLogger
{
    string FileName { get; }

    void Log(string message);
}

class FileLogger : IFileLogger
{
    public string FileName { get; private set; } = "";

    public void Init(string fileName) => FileName = fileName;

    public void Log(string message)
    {
        // Write to file
    }
}

interface IOrderProcessingService
{
    IFileLogger Logger { get; }
}

class OrderProcessingService(IFileLogger logger) : IOrderProcessingService
{
    public IFileLogger Logger { get; } = logger;
}
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

The example creates a service that depends on a logger initialized with a date-based file name. This style keeps the setup concise while still allowing explicit initialization logic. The Tag attribute enables named dependencies for more complex setups. Limitations: compact lambda factories stay readable only while initialization logic remains small. Common pitfalls:

  • Putting heavy imperative setup code into short lambda factories.
  • Forgetting explicit tags when several same-type dependencies exist. See also: Factory, Tags.

The following partial class will be generated:

partial class Composition
{
  public IOrderProcessingService OrderService
  {
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    get
    {
      FileLogger transientFileLogger344;
      FileLogger localLogger4 = new FileLogger();
      DateTime transientDateTime346 = DateTime.Today;
      DateTime localDate = transientDateTime346;
      localLogger4.Init($"app-{localDate:yyyy-MM-dd}.log");
      transientFileLogger344 = localLogger4;
      return new OrderProcessingService(transientFileLogger344);
    }
  }
}

Class diagram:

---
 config:
  maxTextSize: 2147483647
  maxEdges: 2147483647
  class:
   hideEmptyMembersBox: true
---
classDiagram
	FileLogger --|> IFileLogger
	OrderProcessingService --|> IOrderProcessingService
	Composition ..> OrderProcessingService : IOrderProcessingService OrderService
	FileLogger *--  DateTime : "today"  DateTime
	OrderProcessingService *--  FileLogger : IFileLogger
	namespace Pure.DI.UsageTests.Basics.SimplifiedFactoryScenario {
		class Composition {
		<<partial>>
		+IOrderProcessingService OrderService
		}
		class FileLogger {
				<<class>>
		}
		class IFileLogger {
			<<interface>>
		}
		class IOrderProcessingService {
			<<interface>>
		}
		class OrderProcessingService {
				<<class>>
			+OrderProcessingService(IFileLogger logger)
		}
	}
	namespace System {
		class DateTime {
				<<struct>>
		}
	}
Loading