If you've ever used Windsor Installers then you know what I'm talking about. You can have different installers for different parts of the application (repositories, logic, etc.)
public class RepositoriesInstaller : IWindsorInstaller
{
public void Install(IWindsorContainer container, IConfigurationStore store)
{
container.Register(...);
}
}
And then we could call the installer from the Windsor bootstrapper like so
var container = new WindsorContainer();
container.Install(new RepositoriesInstaller());
Does asp.net core have anything similar?
If not I would implement it like so
public interface IServiceConfiguration
{
void Install(IServiceCollection services);
}
public class DomainServiceConfiguration : IServiceConfiguration
{
public void Install(IServiceCollection services)
{
services.AddScoped(...);
}
}
And then call this from the startup file
new DomainServiceConfiguration().Install(services);
So as many people mentioned in the comments, the IOC container in asp.net core is simple and light weight. However it is extensible.
The convention would be to write an extension method in a different file and call in the ConfigureServices
method (So core's DI has no such thing as a module installer interface). This answers the question I posted originally.
My argument was that you would not be able to register the methods by convention. I.e. create the extension method and not have to worry about adding it to the ConfigureServices
class.
I was wrong, this can be done. Here's the code:
This class lives in any .cs file within your assembly
public static class MyInstaller
{
public static void Install(this IServiceCollection services)
{
// register stuff here
}
}
Add This Method to your Startup.cs file
void LoadInstaller(Type type, IServiceCollection services)
{
var installMethods= type.GetMethods(BindingFlags.Static | BindingFlags.Public).Where(mi => mi.Name == "Install");
var installMethod = installMethods.First();
installMethod.Invoke(null, new object[] { services });
}
Add this to your ConfigureServices
method
var assemblies = AppDomain.CurrentDomain.GetAssemblies().
Where(assembly => assembly.GetName().Name.Contains("MyAssemblyName"));
foreach (var assembly in assemblies)
{
var types = assembly.GetTypes().Where(t => t.IsClass && t.IsPublic && t.Name.Contains("Installer")); // You can create your own convention here, make sure it won't conflict with other class names that are not meant to be installers
foreach (var installerType in types)
{
LoadInstaller(installerType, services);
}
}
Now you can add installers by convention and you never have to manually call the extension method for each new installer. The code could be cleaned up by adding error handling and throwing useful exceptions. But the idea is sound.
EDIT:
Seeing that this answer seems to gaining attention, I thought I'd add Microsoft's recommendation to a similar problem
Each services.Add{SERVICE_NAME} extension method adds, and potentially configures, services. We recommended that apps follow this convention. Place extension methods in the Microsoft.Extensions.DependencyInjection namespace to encapsulate groups of service registrations. Including the namespace portion Microsoft.Extensions.DependencyInjection for DI extension methods also:
Allows them to be displayed in IntelliSense without adding additional using blocks. Prevents excessive using statements in the Program or Startup classes where these extension methods are typically called.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With