Skip to content

Latest commit

 

History

History
182 lines (158 loc) · 5.24 KB

File metadata and controls

182 lines (158 loc) · 5.24 KB

Manually started tasks

By default, tasks are started automatically when they are injected. But you can override this behavior as shown in the example below. It is also recommended to add a binding for CancellationToken to be able to cancel the execution of a task.

using Pure.DI;

DI.Setup(nameof(Composition))
    // Overrides the default binding that performs an auto-start of a task
    // when it is created. This binding will simply create the task.
    // The start will be handled by the consumer.
    .Bind<Task<TT>>().To(ctx => {
        ctx.Inject(ctx.Tag, out Func<TT> factory);
        ctx.Inject(out CancellationToken cancellationToken);
        return new Task<TT>(factory, cancellationToken);
    })
    // Specifies to use CancellationToken from the composition root argument,
    // if not specified, then CancellationToken.None will be used
    .RootArg<CancellationToken>("cancellationToken")
    .Bind<IUserPreferences>().To<UserPreferences>()
    .Bind<IDashboardService>().To<DashboardService>()

    // Composition root
    .Root<IDashboardService>("GetDashboard");

var composition = new Composition();
using var cancellationTokenSource = new CancellationTokenSource();

// Creates a composition root with the CancellationToken passed to it
var dashboard = composition.GetDashboard(cancellationTokenSource.Token);
await dashboard.LoadAsync(cancellationTokenSource.Token);

interface IUserPreferences
{
    ValueTask LoadAsync(CancellationToken cancellationToken);
}

class UserPreferences : IUserPreferences
{
    public ValueTask LoadAsync(CancellationToken cancellationToken) => ValueTask.CompletedTask;
}

interface IDashboardService
{
    Task LoadAsync(CancellationToken cancellationToken);
}

class DashboardService : IDashboardService
{
    private readonly Task<IUserPreferences> _preferencesTask;

    public DashboardService(Task<IUserPreferences> preferencesTask)
    {
        _preferencesTask = preferencesTask;
        // The task is started manually in the constructor.
        // This allows the loading of preferences to begin immediately in the background,
        // while the service continues its initialization.
        _preferencesTask.Start();
    }

    public async Task LoadAsync(CancellationToken cancellationToken)
    {
        // Wait for the preferences loading task to complete
        var preferences = await _preferencesTask;
        await preferences.LoadAsync(cancellationToken);
    }
}
Running this code sample locally
dotnet --list-sdk
  • Create a net10.0 (or later) console application
dotnet new console -n Sample
  • Add a reference to the NuGet package
dotnet add package Pure.DI
  • Copy the example code into the Program.cs file

You are ready to run the example 🚀

dotnet run

Important

The method Inject()cannot be used outside of the binding setup.

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

  [MethodImpl(MethodImplOptions.AggressiveInlining)]
  public IDashboardService GetDashboard(CancellationToken cancellationToken)
  {
    Task<IUserPreferences> transientTask422;
    Func<IUserPreferences> perBlockFunc423 = new Func<IUserPreferences>(
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    () =>
    {
      return new UserPreferences();
    });
    Func<IUserPreferences> localFactory4 = perBlockFunc423;
    CancellationToken localCancellationToken1 = cancellationToken;
    transientTask422 = new Task<IUserPreferences>(localFactory4, localCancellationToken1);
    return new DashboardService(transientTask422);
  }
}

Class diagram:

---
 config:
  maxTextSize: 2147483647
  maxEdges: 2147483647
  class:
   hideEmptyMembersBox: true
---
classDiagram
	UserPreferences --|> IUserPreferences
	DashboardService --|> IDashboardService
	Composition ..> DashboardService : IDashboardService GetDashboard(System.Threading.CancellationToken cancellationToken)
	DashboardService *--  TaskᐸIUserPreferencesᐳ : TaskᐸIUserPreferencesᐳ
	TaskᐸIUserPreferencesᐳ o-- CancellationToken : Argument "cancellationToken"
	TaskᐸIUserPreferencesᐳ o-- "PerBlock" FuncᐸIUserPreferencesᐳ : FuncᐸIUserPreferencesᐳ
	FuncᐸIUserPreferencesᐳ *--  UserPreferences : IUserPreferences
	namespace Pure.DI.UsageTests.BCL.ManualTaskScenario {
		class Composition {
		<<partial>>
		+IDashboardService GetDashboard(System.Threading.CancellationToken cancellationToken)
		}
		class DashboardService {
				<<class>>
			+DashboardService(TaskᐸIUserPreferencesᐳ preferencesTask)
		}
		class IDashboardService {
			<<interface>>
		}
		class IUserPreferences {
			<<interface>>
		}
		class UserPreferences {
				<<class>>
			+UserPreferences()
		}
	}
	namespace System {
		class FuncᐸIUserPreferencesᐳ {
				<<delegate>>
		}
	}
	namespace System.Threading {
		class CancellationToken {
				<<struct>>
		}
	}
	namespace System.Threading.Tasks {
		class TaskᐸIUserPreferencesᐳ {
				<<class>>
		}
	}
Loading