Skip to content

Latest commit

 

History

History
158 lines (135 loc) · 3.69 KB

File metadata and controls

158 lines (135 loc) · 3.69 KB

Factory with thread synchronization

In some cases, initialization of objects requires synchronization of the overall composition flow. This scenario demonstrates how to use factories with thread synchronization to ensure proper initialization order.

using Shouldly;
using Pure.DI;

DI.Setup(nameof(Composition))
    .Bind<IMessageBus>().To<IMessageBus>(ctx => {
        // Initialization logic requiring synchronization
        // of the overall composition flow.
        // For example, connecting to a message broker.
        lock (ctx.Lock)
        {
            ctx.Inject(out MessageBus bus);
            bus.Connect();
            return bus;
        }
    })
    .Bind<INotificationService>().To<NotificationService>()

    // Composition root
    .Root<INotificationService>("NotificationService");

var composition = new Composition();
var service = composition.NotificationService;
service.Bus.IsConnected.ShouldBeTrue();

interface IMessageBus
{
    bool IsConnected { get; }
}

class MessageBus : IMessageBus
{
    public bool IsConnected { get; private set; }

    public void Connect() => IsConnected = true;
}

interface INotificationService
{
    IMessageBus Bus { get; }
}

class NotificationService(IMessageBus bus) : INotificationService
{
    public IMessageBus Bus { get; } = bus;
}
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

Thread synchronization in factories should be used carefully as it may impact performance. Only use when necessary for correct initialization behavior.

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

  public INotificationService NotificationService
  {
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    get
    {
      IMessageBus transientIMessageBus56;
      // Initialization logic requiring synchronization
      // of the overall composition flow.
      // For example, connecting to a message broker.
      lock (_lock)
      {
        MessageBus localBus = new MessageBus();
        localBus.Connect();
        {
          transientIMessageBus56 = localBus;
          goto transientIMessageBus56Finish;
        }
      }

      transientIMessageBus56Finish:
        ;
      return new NotificationService(transientIMessageBus56);
    }
  }
}

Class diagram:

---
 config:
  maxTextSize: 2147483647
  maxEdges: 2147483647
  class:
   hideEmptyMembersBox: true
---
classDiagram
	NotificationService --|> INotificationService
	Composition ..> NotificationService : INotificationService NotificationService
	IMessageBus *--  MessageBus : MessageBus
	NotificationService *--  IMessageBus : IMessageBus
	namespace Pure.DI.UsageTests.Advanced.FactoryWithThreadSynchronizationScenario {
		class Composition {
		<<partial>>
		+INotificationService NotificationService
		}
		class IMessageBus {
				<<interface>>
		}
		class INotificationService {
			<<interface>>
		}
		class MessageBus {
				<<class>>
			+MessageBus()
		}
		class NotificationService {
				<<class>>
			+NotificationService(IMessageBus bus)
		}
	}
Loading