In this article, I explain how to use an interface called IServiceInstaller which you can use when you want to configure Dependency Injections and then read it automatically 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)
{
services.AddControllers(options => { options.Filters.Add(new AuthorizeFilter()); })
.AddNewtonsoftJson();
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();
#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
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.