ASP.NET Core Inject All Dependencies in the Assembly

ASP.NET Core would very much like you to use the built in dependency injection system rather than a substitute like Autofac:

The built-in service container is meant to serve the needs of the framework and most consumer apps. We recommend using the built-in container unless you need a specific feature that it doesn’t support.

While I think I’d struggle without “Func support for lazy initialization”, the feature I want the most is assembly-wide service registration. This means instead of having to create a new services.AddTransient() for every class, I can add a new interface and class pair and be confident it will be added to the dependency container.

My solution to this is to find all the classes in my assembly which have an interface name which is exactly the classname, preceded by a capital I, and registered them as transients.

One further twist is that some services need to be registered manually, and thus may need to be removed from the collection of automatically added services. They may also need a different lifetime. To support this the AddService method removes any existing registrations for the interface type before creating the new one. It also takes the implementation type as a factory allowing transient, scoped, and singleton implementations in the one method.

public virtual void RegisterServices(IServiceCollection services)
{
  var assy = Assembly.GetCallingAssembly();
  var types = assy.GetTypes().Where(t => t.IsClass && !t.IsAbstract && !t.IsGenericType && !t.IsNested);
  foreach(var type in types)
  {
    var iface = type.GetInterface("I" + type.Name);
    if (iface != null && iface.Assembly.FullName == assy.FullName)
      AddService(services, iface, (_) => Activator.CreateInstance(type), ServiceLifetime.Transient);
  }

  // register services that take configuration data
  var fileStorage = new FileStorage(Configuration.GetConnectionString("..."));
  AddService(services, typeof(IFileStorage), (_) => fileStorage, ServiceLifetime.Singleton);
}

public void AddService(IServiceCollection services, Type tInterface, Func factory, ServiceLifetime lifetime)
{
  var existing = services.SingleOrDefault(s => s.ServiceType.FullName == tInterface.FullName);
  if (existing != null)
    services.Remove(existing);

  services.Add(new ServiceDescriptor(tInterface, factory, lifetime));
}