Skip to content

Latest commit

 

History

History
172 lines (151 loc) · 5.52 KB

task.md

File metadata and controls

172 lines (151 loc) · 5.52 KB

Task

CSharp

By default, tasks are started automatically when they are injected. It is recommended to use an argument of type CancellationToken to the composition root to be able to cancel the execution of a task. In this case, the composition root property is automatically converted to a method with a parameter of type CancellationToken. To start a task, an instance of type TaskFactory is used, with default settings:

  • CancellationToken.None
  • TaskScheduler.Default
  • TaskCreationOptions.None
  • TaskContinuationOptions.None

But you can always override them, as in the example below for TaskScheduler.Current.

interface IDependency
{
    ValueTask DoSomething(CancellationToken cancellationToken);
}

class Dependency : IDependency
{
    public ValueTask DoSomething(CancellationToken cancellationToken) => ValueTask.CompletedTask;
}

interface IService
{
    Task RunAsync(CancellationToken cancellationToken);
}

class Service(Task<IDependency> dependencyTask) : IService
{
    public async Task RunAsync(CancellationToken cancellationToken)
    {
        var dependency = await dependencyTask;
        await dependency.DoSomething(cancellationToken);
    }
}

DI.Setup(nameof(Composition))
    .Hint(Hint.Resolve, "Off")
    // Overrides TaskScheduler.Default if necessary
    .Bind<TaskScheduler>().To(_ => TaskScheduler.Current)
    // Specifies to use CancellationToken from the composition root argument,
    // if not specified then CancellationToken.None will be used
    .RootArg<CancellationToken>("cancellationToken")
    .Bind<IDependency>().To<Dependency>()
    .Bind<IService>().To<Service>()

    // Composition root
    .Root<IService>("GetRoot");

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

// Creates a composition root with the CancellationToken passed to it
var service = composition.GetRoot(cancellationTokenSource.Token);
await service.RunAsync(cancellationTokenSource.Token);

The following partial class will be generated:

partial class Composition
{
  private readonly Composition _root;

  [OrdinalAttribute(10)]
  public Composition()
  {
    _root = this;
  }

  internal Composition(Composition parentScope)
  {
    _root = (parentScope ?? throw new ArgumentNullException(nameof(parentScope)))._root;
  }

  [MethodImpl(MethodImplOptions.AggressiveInlining)]
  public IService GetRoot(CancellationToken cancellationToken)
  {
    TaskFactory<IDependency> perBlockTaskFactory3;
    CancellationToken localCancellationToken53 = cancellationToken;
    TaskCreationOptions transientTaskCreationOptions4 = TaskCreationOptions.None;
    TaskCreationOptions localTaskCreationOptions54 = transientTaskCreationOptions4;
    TaskContinuationOptions transientTaskContinuationOptions5 = TaskContinuationOptions.None;
    TaskContinuationOptions localTaskContinuationOptions55 = transientTaskContinuationOptions5;
    TaskScheduler transientTaskScheduler6 = TaskScheduler.Current;
    TaskScheduler localTaskScheduler56 = transientTaskScheduler6;
    perBlockTaskFactory3 = new TaskFactory<IDependency>(localCancellationToken53, localTaskCreationOptions54, localTaskContinuationOptions55, localTaskScheduler56);
    Func<IDependency> perBlockFunc2 = new Func<IDependency>([MethodImpl(MethodImplOptions.AggressiveInlining)] () =>
    {
      IDependency localValue57 = new Dependency();
      return localValue57;
    });
    Task<IDependency> transientTask1;
    // Injects an instance factory
    Func<IDependency> localFactory58 = perBlockFunc2;
    // Injects a task factory creating and scheduling task objects
    TaskFactory<IDependency> localTaskFactory59 = perBlockTaskFactory3;
    // Creates and starts a task using the instance factory
    transientTask1 = localTaskFactory59.StartNew(localFactory58);
    return new Service(transientTask1);
  }
}

Class diagram:

---
 config:
  class:
   hideEmptyMembersBox: true
---
classDiagram
	Service --|> IService
	Dependency --|> IDependency
	Composition ..> Service : IService GetRoot(System.Threading.CancellationToken cancellationToken)
	Service *--  TaskᐸIDependencyᐳ : TaskᐸIDependencyᐳ
	TaskᐸIDependencyᐳ o-- "PerBlock" FuncᐸIDependencyᐳ : FuncᐸIDependencyᐳ
	TaskᐸIDependencyᐳ o-- "PerBlock" TaskFactoryᐸIDependencyᐳ : TaskFactoryᐸIDependencyᐳ
	FuncᐸIDependencyᐳ *--  Dependency : IDependency
	TaskFactoryᐸIDependencyᐳ o-- CancellationToken : Argument "cancellationToken"
	TaskFactoryᐸIDependencyᐳ *--  TaskCreationOptions : TaskCreationOptions
	TaskFactoryᐸIDependencyᐳ *--  TaskContinuationOptions : TaskContinuationOptions
	TaskFactoryᐸIDependencyᐳ *--  TaskScheduler : TaskScheduler
	namespace Pure.DI.UsageTests.BCL.TaskScenario {
		class Composition {
		<<partial>>
		+IService GetRoot(System.Threading.CancellationToken cancellationToken)
		}
		class Dependency {
			+Dependency()
		}
		class IDependency {
			<<interface>>
		}
		class IService {
			<<interface>>
		}
		class Service {
			+Service(TaskᐸIDependencyᐳ dependencyTask)
		}
	}
	namespace System {
		class FuncᐸIDependencyᐳ {
				<<delegate>>
		}
	}
	namespace System.Threading {
		class CancellationToken {
				<<struct>>
		}
	}
	namespace System.Threading.Tasks {
		class TaskContinuationOptions {
				<<enum>>
		}
		class TaskCreationOptions {
				<<enum>>
		}
		class TaskFactoryᐸIDependencyᐳ {
		}
		class TaskScheduler {
				<<abstract>>
		}
		class TaskᐸIDependencyᐳ {
		}
	}
Loading