Microsoft’s documentation says “ASP.NET Core is designed from the ground up to support and leverage dependency injection”. It also says that “Dependency injection (DI) is a technique for achieving loose coupling between objects and their collaborators, or dependencies.” (read Martin Fowler’s article for the in-depth coverage of DI).
I have used DI for years and I love it – it allows me to compartmentalize my applications and have DI link everything up at run time. The only chore is making sure all my services are registered properly at startup. This article is about a library I build to automatically register classes in an assembly into Microsoft’s DI provider (known as a DI container).
UPDATE: New features added in version 2.
Now has attributes for defining the ServiceLifetime of your classes, e.g. adding the [RegisterAsScoped] attribute to a class will mean its ServiceLifetime in the DI will be set to Scoped. Thanks to Fedor Zhekov (GitHub @ZFi88).
TL;DR; – summary
This article introduces a small library called NetCore.AutoRegisterDi (NuGet link) that can automatically register classes with interfaces in an assembly into the built-in ASP.NET Core DI container. The reason I built this library is because ASP.NET Core’s DI container turns out to be quick – at least 5 times quicker than AutoFac. I also describe how I use this in applications that have a lot of assemblies.
Setting the scene
The typical approach shown in the Microsoft’s documentation to registering services is to add a line of code to register each service in the ConfigureServices method in ASP.NET Core’s Startup class. For me that is a horrible maintenance issue, because I might forget to register a service I need: and if I do forget then my application will fail when that service is used.
Until now my go-to solution for automatically registering my services in DI is AutoFac’s RegisterAssemblyTypes method. But when I saw David Fowler’s tweet with a link to a set of dependency Injection container benchmarks, I found out that the ASP.NET Core DI container is a lot faster than AutoFac.
I worry about performance, so I thought – how hard would it be to build a similar extension to AutoFac’s RegisterAssemblyTypes method, but for the NET Core DI container, Microsoft.Extensions.DependencyInjection? Turns out it was easy (2 hours + 2 hours for NuGet+docs). This article is about how you can use the NetCore.AutoRegisterDi in your own applications.
NOTE: Microsoft docs says, “The default services container provided by ASP.NET Core provides a minimal feature set and isn’t intended to replace other containers.” However, I find Microsoft’s DI library has all the things I need for most applications, but some features aren’t well publicised – see Steve Gordon’s articles on three Microsoft DI features that I had to find the hard way:
- NET Core Dependency Injection – How to Register Generic Types
- NET Core Dependency Injection – Registering Implementations Using Delegates
- NET Core Dependency Injection – Registering Multiple Implementations of an Interface
Introduction to DI – what is a service?
Note: If you already understand DI you can skip this section.
I refer to a service, which is a combination of a class that implements that service, known as the implementation type in the NET Core DI container, which is linked (known as registered) to a service type, which is typically an interface. Here is an example of an interface, followed by the class that implements that interface.
public interface IMyService
{
string IntToString(int num);
}
public class MyService : IMyService, C
{
public string IntToString(int num)
{
return num.ToString();
}
}
There are various ways to use a service in another class. The standard way is to add a parameter to the class’s construction and the DI container will resolve that interface to the implementation class – this is known as constructor injection. Here is an example.
public class UseService
{
private readonly IMyService _service;
public UseService(IMyService service)
{
_service = service;
}
public string CallService()
{
int i = 1; //... some calculation
return _service.IntToString(i);
}
}
This interface/class pattern “achieving loose coupling between objects and their collaborators” (to quote Microsoft). This has lots of benefits, but here are the two main ones for me:
- The interface clearly defines the properties, methods, classes etc. that user of the service can access. By using an interface, I can’t access things I’m not supposed to use, so interfaces make me focus on what I should use and ignore the rest.
- The two classes are “loosely coupled”, i.e. it is easy to replace the original version of the implementing class if it conforms to the interface. This is especially useful when unit testing, as it’s easy to replace the interface with a mock that allows you to test the UseService class on its own.
How to NetCore.AutoRegisterDi works
The NetCore.AutoRegisterDi library is very simple – it will scan an assembly, or a collection of assemblies to find classes that a) are simple classes (not generic, not abstract, not nested) that have interfaces and b) have an interface(s). It will then register each class with its interfaces with the NET Core DI provider.
Here is simple example of calling this library to register all the valid classes in the current assembly (also known as a project).
service.RegisterAssemblyPublicNonGenericClasses()
.AsPublicImplementedInterfaces();
That’s simple example, but one I use that all the time. That’s because in every project that has classes to register with the DI provider, I add a simple wrapper extension method which handles all my DI registering, as shown below
public static class NetCoreDiSetupExtensions
{
public static void RegisterServiceLayerDi
(this IServiceCollection services)
{
services.RegisterAssemblyPublicNonGenericClasses()
.AsPublicImplementedInterfaces();
//put any non-standard DI registration, e.g. generic types, here
}
}
The idea of the code above is that the NetCore.AutoRegisterDi library deals with all the standard class DI registering. In the few times I need a more complex type registered, say a generic type such as BlobRepository<T>, then I add extra code to handle the registering manually.
Then, I call the RegisterServiceLayerDi extension in ASP.NET Core’s Startup class like this.
public void ConfigureServices(IServiceCollection services) //#A
{
services.AddControllersWithViews()
//… code setup code left out
services.RegisterServiceLayerDi();
services.RegisterBizLogic();
//... and so on - one for each project that needs DI registering
}
In case you need it the NetCore.AutoRegisterDi code has various parts that give you more control if you need it. Here is an example with the four extension methods.
service.RegisterAssemblyPublicNonGenericClasses(… your assembly ref goes here …)
.Where(x => x.Name.EndsWith(“Service”)) //optional
.IgnoreThisInterface<IMyInterface>() //optional
.AsPublicImplementedInterfaces(ServiceLifetime.Scoped);
- The first line finds all the public, non-generic classes (see docs for detailed definition of what classes it finds) in the assembly you provide (or assemblies – it takes params Assembly[] assemblies), or if there are no parameters it scans the assemble in which the method is called.
- The Where method in the second line is optional and it allows you to filter the classes if you need to.
- By default this library won’t register a class against the IDisposable and ISerializable interfaces,but you might want to add other interfaces to the interface ignore list. To do that you can use the IgnoreThisInterface method to do that. NOTE: You can call to the IgnoreThisInterface method multiple times to add each interface to ignore.
- The final line finds all the public, non-nested interfaces (apart from IDisposable) that each class implements and registers each interface against the class. It has an optional lifetime property which defaults to ServiceLifetime.Transient, but as shown on line three you can define another lifetime (but be warned – most services should be Transient).
The AsPublicImplementedInterfaces method takes an optional parameter of the ServiceLifetime you want for the service. It defaults to Transient lifetime where a new service instance is created on every injection, which is a good default for services. The other options are Singleton (same instance used on every injection) or Scoped (a new service instance is created for each HTTP request).
NOTE: See the NetCore.AutoRegisterDi README file for the full documentation.
Using attributes to define the lifetime of a service
One improvement that has been added to NetCore.AutoRegisterDi is the ability to define the lifetime of your service by using attributes, for example:
[RegisterAsScoped]
public class MyOtherScopeService : IMyOtherService
{
public string Result { get; }
}
There are four attributes, which will override any setting given AsPublicImplementedInterfaces method.
- [DoNotAutoRegister] – tells NetCore.AutoRegisterDi to not register this class.
- [RegisterAsTransient] – this class will be registered with a lifetime of Transient
- [RegisterAsScoped] – this class will be registered with a lifetime of Scoped.
- [RegisterAsSingleton] – this class will be registered with a lifetime of Singleton.
Debugging your DI registrations
Sometimes its useful to see what the NetCore.AutoRegisterDi has registered with the .NET DI provider. In release 2.1.0 I added a return from the final stage to return a list of a) the interfaces it has ignored and b) what classes where registered with the NET DI provider.
To do this you need to capture the list of results coming out of the AsPublicImplementedInterfaces method, as shown in the code below.
var results = service
.RegisterAssemblyPublicNonGenericClasses()
.IgnoreThisInterface<IAnotherInterface>()
.AsPublicImplementedInterfaces();
Then, if you put a breakpoint just after this code, then you can hover of the results variable and get a view on what was registered. See image below.

Conclusion
DI is a great tool and one that I use a lot. The problem is in real applications I can have many hundreds (maybe thousands) of DI services so I want the DI to a) be easy to set up and b) be fast. I fact I think not automatically registering your services is an anti-pattern because it’s so easy to forget to register a service, and your live application will fail when that service is used.
I used to use AutoFac’s RegisterAssemblyTypes method, but that was about the only feature I used. Now that I have the NetCore.AutoRegisterDi library I have an assembly scanning feature that works with ASP.NET Core’s built-in DI container, and it makes my DI faster.
PS. Andrew Lock recommends a DI library called Scrutor – see his article called “Using Scrutor to automatically register your services with the ASP.NET Core DI container“. That might fit your needs better than my library.
Hi there to all, for the reason that I am genuinely keen of reading this website’s post to be updated on a regular basis. It carries pleasant stuff.
Glad you like this article. The information in this article is up to date and NuGet library works with any .NET version because it uses the Net standard 2.0.
To date the NetCore.AutoRegisterDi NuGet package has been downloaded 1.7 million times, so people find it useful.
Does this work with latest version of DI v7.0?
Hi James,
I will be updating this library to .NET 7 but the current .NET 6 version should work with .NET 7 because this library uses very basic features like read/write files.Sorry James, I assumed you were talking about another library (I have +10 active libraries). The NetCore.AutoRegisterDi library has a target framework of netstandard2.0, so it will work for with ASP.NET Core 2 and onwards, so it will work with .NET 7 code.
This is great ! But what if I want to register all services from multiple assemblies based on assembly name which follows certain conventions like Starts with “CompanyName” for example?
Hi Alok,
The RegisterAssemblyPublicNonGenericClasses extension method takes has the parameters (this IServiceCollection services, params Assembly[] assemblies), so you can provide multiple assemblies to scan, e.g.
Hi Jon, Say If I have many assemblies from other projects which are referenced in the current project. And how can I find them by “name”? I tried to
And I passed them to Register method and it registers successfully. But It can’t still resolve the service.
I don’t know, but the code is so small (see https://github.com/JonPSmith/NetCore.AutoRegisterDi/blob/master/NetCore.AutoRegisterDi/AutoRegisterHelpers.cs ) you could copy it and debug it.
Remember that the classes have to be public, not nested and the interfaces must be public too.
Assembly.LoadFile and other static functions in Assembly have an attribute:
[RequiresUnreferencedCode(“Types and members the loaded assembly depends on might be removed”)]
I read another article about someone using AutoFac to wire up all the dependencies. I thought well I like AutoFac (and have used it) but I only want to use Microsoft’s .NET Core DI… then came across your awesome post!
Hi Regency,
Yep, I think Microsoft’s DI is great – its fast, built-in and handles everything I need. Just a bit of work to automate things and its all fine.
Superb, i am looking for simple DI for my .net core application, I have using AutoRegisterDi but i am getting “Object reference not set to an instance of an object” exception while calling controller.
Step 1 : I have external dll which is implemented by using Interface in it. like
public class AlgorithamCalculator : IAlgorithamCalculation
{
//Implimentation
.}
step 2 : I want to use this AlgorithamCalculator in my project , i have created local interface class as IAlgorithamCalculation . Now In my Startup.cs class i am calling dll class like this
var assemblyScan = Assembly.GetAssembly(typeof(AlgorithamCalculator )); // here it gets the dll
services.RegisterAssemblyPublicNonGenericClasses(assemblyScan)
.Where(c => c.Name.Equals(“AlgorithamCalculator “))
.AsPublicImplementedInterfaces();
Step3: I am calling this my controller as dependency
private IAlgorithamCalculation _algorithamCalc;
public AlgorithamReportController( IAlgorithamCalculation algorithamCalc )
{
_algorithamCalc = algorithamCalc; // i should access dll functions by using algorithamCalc .
}
when i am calling AlgorithamReport Controller from url , i am getting “Object reference not set to an instance of an object” , i am unable to find what i have missed here , Can you please help me.
Thanks ,
Ravindra.
Hi Ravi,
Try registering manually and check that works. I would also change your Equals test to `Where(c => c.Name.Equals(typeof(AlgorithamCalculator ).Name)) as it safer. Also, my library assumes your interface is public.
If you still have problems then put a breakpoint after the AsPublicImplementedInterfaces and look at the services instance – it will have a very long list of registered items, yours should be near the end.
Awesome! Awesome! I was doing similar with Autofac and moving the app to core and wanted to explore my options and have way too many interfaces to code them all out in ConfigureServices
Hi Chris,
Glad you found it useful. Andrew Lock (author of ASP.NET Core in Action) pointed out there is similar library at https://github.com/khellang/Scrutor – you may want to look at that too.
This is a big time saver, thank you!
if we have a “Clean Architecture” approach; how to inject DbContext without referencing the Infrastructure. I’m using this approach but
simply it cant resolve the DbContext.
Thank you again and amazing article btw (y)
Hi besartkuleta,
I’m not sure what you mean by “inject DbContext without referencing the Infrastructure”. Do you mean without access to DI? That’s difficult.
Give me some clues and I’ll try to answer.
Let’s say I have separated my project into three layers; WebApi, Core and Infrastructure.
The Api and Infrastructure have a reference of Core but they can’t have reference of each other.
So I want to inject DbContext (which stays in infrastructure) without giving a reference to WebApi. (hope I was clear)
OK, I see your problem. Basically you have to have the DbContext defined so that Core can access it, which throws your assembly structure out.
The first question is “why you you need to access the DbContext in the Core layer”, as that will tell you something about what your Core is doing. Does it access the classes mapped to the database as well? If it does then you need a assembly below Core holding the EF Core parts (I call this the DataLayer).
If you are only passing the DbContext through, then you can use the trick of using the generic DbContext type (you will need to the Microsoft.EntityFrameworkCore package, but you don’t need your real DbContext). Then in your DI setup you using something like this.
services.AddScoped(d => d.GetRequiredService() )
BUT that makes things a bit harder (you don’t have a strongly typed DbContext when passing to other methods) and your really need to think if this is better than having a lower DataLayer assembly.
” it’s so easy to forget to register a service, and your live application will fail when that service is used”
And how did you test your solution that it magically found the service when ran locally and in pre-production ?
In my unit tests I often add checks on the registering of services if I think there may be a problem. Have a look at the test in the NetCore.AutoRegisterDi test code – https://github.com/JonPSmith/NetCore.AutoRegisterDi/blob/master/Test/TestAutoRegisterDi.cs
Pretty simple, but effective.
Hello Jon,
I’m relatively new to C# .NET (MVC and Web API), but I have programmed in other languages for years using MVC and DI. So I understand concepts mostly well, but not necessarily how to accomplish things.
The main item I trying to figure out how to register are my DbContext classes. I am trying to figure out how I replace this next line with something using this project.
services.AddDbContext(options => options.UseMySQL(Configuration.GetConnectionString("DefaultConnection")));
I am using .NET Core, Entity Framework Core, and MySQL as my DB.
How do you deal with objects out of diffrent namespaces?
I have my controllers in a diffrent namespace, then my services.
The problem that i am having is that the where c only looks at classes in the namespace of the startup.
But my logic is placed in a diffrent namespace, and i can’t find anything that says how to solve this problem.
services.RegisterAssemblyPublicNonGenericClasses()
.Where(c => c.Name.EndsWith(“Service”))
.AsPublicImplementedInterfaces();
The code you show will register classes+interfaces in the assembly you are in covering all the namespaces in that assembly. So if you run it in Startup it will only look for classes+interfaces in your ASP.NET Core assembly.
If you need to register one or more other assemblies you can. I give one example in this article – see https://www.thereformedprogrammer.net/asp-net-core-fast-and-automatic-dependency-injection-setup/#an-approach-to-using-autoregisterdi-in-real-applications
Also have a look at the ReadMe file in the git repo – https://github.com/JonPSmith/NetCore.AutoRegisterDi/blob/master/READMe.md for more examples.
Thanks a lot @JonPSmith:disqus for wonderful article. I tried to implement in my application and came across an issue. I have submitted the issue at : https://stackoverflow.com/questions/59983697/some-services-are-not-able-to-be-constructed-using-the-library-netcore-autoreg
Can you please help me to get your thoughts on this issue
I like this tutorial, but it is hard to read unformatted code.
Hi Omar,
Thanks for calling me out on that. I edited the article to say the library has been updated and the newer WordPress altered the code. I have now updated the code and also added more changes
Ok Jon, thank you for your time and effort.