Configuring Dependency Injections in .NET Core without any Code using Service Installer





5.00/5 (3 votes)
How to use an interface called IServiceInstaller that you can use to configure Dependency Injections and then automatically read it with a simple line of reflection code
Introduction
This is how we configure IServiceInstaller
interface:
public interface IServiceInstaller
{
void InstallServices(IServiceCollection services,
AppSettings appSettings, Assembly startupProjectAssembly);
}
Description
The “appSettings
” parameter is a class that contains all of “appsettings.json” file configuration values. You can use IConfiguration
indeed and pass the object to StartUp
class. The “startupProjectAssembly
” parameter is used when you want to implement these files in another layer except API Layer.
Then this is how we use reflection to implement an extension method for ConfigureServices
method:
public static class ServiceInstallerExtensions
{
public static void InstallServicesInAssemblies
(this IServiceCollection services, AppSettings appSettings)
{
var startupProjectAssembly = Assembly.GetCallingAssembly();
var assemblies = new[] { startupProjectAssembly, Assembly.GetExecutingAssembly() };
var installers = assemblies.SelectMany(a => a.GetExportedTypes())
.Where(c => c.IsClass && !c.IsAbstract
&& c.IsPublic && typeof(IServiceInstaller).IsAssignableFrom(c))
.Select(Activator.CreateInstance).Cast<IServiceInstaller>().ToList();
installers.ForEach(i => i.InstallServices
(services, appSettings, startupProjectAssembly));
}
}
Eventually, after adding all services, we implement ConfigureServices
method like this:
public void ConfigureServices(IServiceCollection services)
{
//* HttpContextAccessor
// services.AddHttpContextAccessor();
//* Controllers
services.AddControllers(options => { options.Filters.Add(new AuthorizeFilter()); })
.AddNewtonsoftJson();
//* Installers
services.InstallServicesInAssemblies(_appSettings);
}
Finished. Now all the services with implementing the IServiceInstaller
will be registered automatically in ConfigureServices
.
We use AutoRegisterDi
Package to automatically register DI Services. Now we build a class called:
public class RegisterServicesUsingAutoRegisterDiInstaller : IServiceInstaller
{
public void InstallServices
(IServiceCollection services, AppSettings appSettings, Assembly startupProjectAssembly)
{
var dataAssembly = typeof(SomeRepository).Assembly;
var serviceAssembly = typeof(SomeService).Assembly;
var webFrameworkAssembly = Assembly.GetExecutingAssembly();
var startupAssembly = startupProjectAssembly;
var assembliesToScan = new[]
{ dataAssembly, serviceAssembly, webFrameworkAssembly, startupAssembly };
#region Generic Type Dependencies
services.AddScoped(typeof(IRepository<>), typeof(Repository<>));
#endregion
#region Scoped Dependency Interface
services.RegisterAssemblyPublicNonGenericClasses(assembliesToScan)
.Where(c => c.GetInterfaces().Contains(typeof(IScopedDependency)))
.AsPublicImplementedInterfaces(ServiceLifetime.Scoped);
#endregion
#region Singleton Dependency Interface
services.RegisterAssemblyPublicNonGenericClasses(assembliesToScan)
.Where(c => c.GetInterfaces().Contains(typeof(ISingletonDependency)))
.AsPublicImplementedInterfaces(ServiceLifetime.Singleton);
#endregion
#region Transient Dependency Interface
services.RegisterAssemblyPublicNonGenericClasses(assembliesToScan)
.Where(c => c.GetInterfaces().Contains(typeof(ITransientDependency)))
.AsPublicImplementedInterfaces(); // Default is Transient
#endregion
#region Register DIs By Name
services.RegisterAssemblyPublicNonGenericClasses(dataAssembly)
.Where(c => c.Name.EndsWith("Repository")
&& !c.GetInterfaces().Contains(typeof(ITransientDependency))
&& !c.GetInterfaces().Contains(typeof(IScopedDependency))
&& !c.GetInterfaces().Contains(typeof(ISingletonDependency)))
.AsPublicImplementedInterfaces(ServiceLifetime.Scoped);
services.RegisterAssemblyPublicNonGenericClasses(serviceAssembly)
.Where(c => c.Name.EndsWith("Service")
&& !c.GetInterfaces().Contains(typeof(ITransientDependency))
&& !c.GetInterfaces().Contains(typeof(IScopedDependency))
&& !c.GetInterfaces().Contains(typeof(ISingletonDependency)))
.AsPublicImplementedInterfaces();
#endregion
}
}
History
- 10th April, 2020: Initial version