Dependency Injection#
This document assumes you're already familiar with the Dependency Injection (DI) pattern. If not, the frameworks listed below describe the pattern in their documentation.
TLDR, How to enable#
dotnet add package CommandDotNet.IoC.MicrosoftDependencyInjection
Install-Package CommandDotNet.IoC.MicrosoftDependencyInjection
Enable MicrosoftDependencyInjection with
appRunner.UseMicrosoftDependencyInjection(...)
dotnet add package CommandDotNet.IoC.Autofac
Install-Package CommandDotNet.IoC.Autofac
Enable Autofac with
appRunner.UseAutofac(...)
dotnet add package CommandDotNet.IoC.SimpleInjector
Install-Package CommandDotNet.IoC.SimpleInjector
Enable SimpleInjector with
appRunner.UseSimpleInjector(...)
No package required
Enable the custom resolver with
appRunner.UseDependencyResolver(myCustomContainer, ...)
Configuration options#
When a resolver is registered, it will be used to resolve instances for
- command classes using
IDependencyResolver.Resolve
IArgumentModel
classes usingIDependencyResolver.TryResolve
.
DI containers have different behaviors for Resolve
and TryResolve
.
In most cases, Resolve
will throw an exception if an instance isn't registered.
Some containers, like MicrosoftDependencyInjection, will return null instead.
When an IDependencyResolver is registered, CommandDotNet will use that
to resolve command classes and argument models. When TryResolve
returns
false or Resolve
returns null, CommandDotNet will attempt to instantiate
the instance using System.Activator
.
UseDependencyResolver
contains the following configuration parameters:
public static AppRunner UseDependencyResolver(
...
Func<CommandContext, IDisposable> runInScope = null,
ResolveStrategy argumentModelResolveStrategy = ResolveStrategy.TryResolve,
ResolveStrategy commandClassResolveStrategy = ResolveStrategy.Resolve
}
- runInScope: if provided, the scope will be created at the beginning of the run and disposed at the end
- argumentModelResolveStrategy: the
ResolveStrategy
used to resolveIArgumentModel
classes. - commandClassResolveStrategy: the
ResolveStrategy
used to resolve command classes.
These parameters also exist for the AutoFac, MicrosoftDependencyInjection and SimpleInjector packages
Custom Resolvers#
To implement another 3rd party resolver, follow the example for one of the existing ones. Submit a PR so we can keep it up-to-date for you.
To implement your own custom resolver, implement the IDependencyResolver
. See the TestDependencyResolver for an example.
Registering all command classes#
Use appRunner.GetCommandClassTypes()
to get all the command class types that could be instantiated from the AppRunner.
This provided several benefits over assembly scanning
- [Command] is not required so there is no guaranteed way to determine a class is a command
- Middleware can dynamically add and remove commands
- There's no need to determine which assemblies to scan, in cases where commands are included from multiple assemblies
- Ignores command classes that are in dev or are temporarily excluded by removing them as subcommands.
private static void RegisterSimpleInjector(this AppRunner appRunner)
{
var container = new SimpleInjector.Container();
foreach(Type type in appRunner.GetCommandClassTypes())
{
container.Register(type);
}
appRunner.UseSimpleInjector(container);
}