Compile-time generated IoC container made possible using Roslyn Code Generators
- Parameterized Factory Registration
- Validation of dependency graph
- Correct error handling and code highlighting
- Transient Registration
- Singleton Registration
- Delegate Registration
- Work with Generic types correctly
- Support for multi-constructor dependencies
- Parameterless Factory Registration
TODO
To create a container class, first inherit the Container
class. Then add your registrations as interfaces to it. Be sure to declare your class as partial so the generated code can be created correctly:
public partial class MyContainer : Container,
Register.Transient<IMyService, MyImplimentation>,
Register.Singleton<MySingletonService, MySingletonService>
{
}
The following registrations are supported:
Register a service that will be instantiated each time the service is injected.
Register.Transient<TService>
Register.Transient<TService, TImplimentation>
Register a service that will be instantiated only on first time it is injected, and will be shared throughout the contianer
Register.Singleton<TService>
Register.Singleton<TService, TImplimentation>
Register a delegate that will be used to create the specified service. The interface will require a method to be created on the nongenerated side that will return the specified service, given a set of dependencies
Register.Delegate<TService>
Register.Delegate<TService, TDependency>
Register.Delegate<TService, TDependency1, TDependency2>
Register.Delegate<TService, TDependency1, TDependency2, TDependency3>
Register.Delegate<TService, TDependency1, TDependency2, TDependency3, TDependency4>
Register.Delegate<TService, TDependency1, TDependency2, TDependency3, TDependency4, TDependency5>
The corresponding required method will look similar to this:
TService Register.Delegate<TService, TDependency>.Create(TDependency dependency)
{
...
}
Register an interface as a factory that can be used to resolve a service when required
Register.Factory<TFactory>
NOTE: Currently only parameterless service creation is possible within factories
You can add the ConstructorFor
attribute on your container in order to have it generate a method to create a specified service type
[ConstructorFor(typeof(MyService))]
public partial class MyContianer : Container,
Register.Transient<MyService>
{
}
To use the container you can simply construct it and call any creat methods that you have included by adding ConstructorFor
attributes, or by calling the Resolve
or TryResolve
methods.
var contianer = new MyContainer();
var myService = container.CreateMyService();
var myOtherService = container.Resolve<MyOtherService>(); // or Resolve(typeof(MyOtherService))
Cogent IoC supports replacing the default ASP.Net Core service provider. This is technically not a full "replacement" of the service provider, but it easily integrates into the default provider and allows resolving dependencies from both Cogent IoC and the ASP.Net service provider.
Instead of using the Container
type, use the AspNetCoreContainer
type. This will add an IServiceProvider
that can be used for delegate registrations to allow access to dependencies in the default Service Provider. Because the container is generated at compile-time you normally can't have direct access to the Service Provider services, but delegate registrations allow you to reference the Service Provider after it has been created.
public partial class MyContainer : AspNetCoreContainer,
Register.Delegate<IConfiguration>
{
IConfiguration Register.Delegate<IConfiguration>.Create()
=> (IConfiguration)ServiceProvider.GetService(typeof(IConfiguration));
}
This will also add a ServiceProviderFactory
for the container to easily replace the Service Provider during startup. During the host builder call the .UseServiceProviderFactory()
method and pass the generated factory method {ContainerName}.ServiceProviderFactory.Create()
// Program.cs
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
}).UseServiceProviderFactory(MyContainer.ServiceProviderFactory.Create());