Skip to main content

Command Palette

Search for a command to run...

Autofac vs Scrutor vs Microsoft.Extensions.DI in .NET: Which Should Your Team Use in 2026?

Updated
โ€ข12 min read
Autofac vs Scrutor vs Microsoft.Extensions.DI in .NET: Which Should Your Team Use in 2026?

Choosing the right dependency injection approach is one of the most consequential architectural decisions a .NET team makes early in a project. Most teams land on Microsoft's built-in container (Microsoft.Extensions.DependencyInjection, or MEDI) by default, and that is usually the right call. But as your application grows โ€” more services, more cross-cutting concerns, more complex registration logic โ€” you start running into the edges of what MEDI can do comfortably. That is where Scrutor and Autofac enter the picture, and where the real decision begins.

๐ŸŽ Want implementation-ready .NET source code you can drop straight into your project? Join Coding Droplets on Patreon for exclusive tutorials, premium code samples, and early access to new content. ๐Ÿ‘‰ https://www.patreon.com/CodingDroplets

This article compares the three most common dependency injection strategies in ASP.NET Core in 2026: the built-in MEDI container, Scrutor (a scanning and decoration extension on top of MEDI), and Autofac (a full-featured third-party IoC container). You will get a clear picture of what each option does well, where each one falls short, and a concrete recommendation for which to use in different team contexts.


What Is the Built-In Microsoft.Extensions.DependencyInjection Container?

MEDI is the DI container that ships with the .NET runtime and is the foundation of every ASP.NET Core application. You register services via IServiceCollection, and the framework resolves them at runtime through IServiceProvider. It supports the three standard lifetimes โ€” Singleton, Scoped, and Transient โ€” along with generic type registration, factory delegates, and keyed services (added in .NET 8).

Where MEDI Excels

MEDI was designed with a specific goal: give library and framework authors a lightweight, unopinionated DI abstraction that third-party IoC containers can sit behind. It is fast, well-tested, deeply integrated with ASP.NET Core, and requires zero additional dependencies. For the majority of applications โ€” APIs, microservices, worker services โ€” it covers all the standard registration patterns without ceremony.

Where MEDI Falls Short

The built-in container begins to show friction in three scenarios: assembly scanning, service decoration, and complex lifetime management. If you need to register every class that implements IRepository<> across multiple assemblies, MEDI requires you to enumerate them manually or write your own reflection loop. If you need to wrap a registered service with a decorator without replacing its existing registration, MEDI has no built-in way to do it. And if you need property injection, child lifetime scopes, or service interception, MEDI simply does not support those patterns.


What Is Scrutor?

Scrutor is a NuGet package by Kristian Hellang that adds two capabilities on top of MEDI: assembly scanning and service decoration. It does not replace the MEDI container โ€” it extends IServiceCollection with the Scan() and Decorate() extension methods. Your application still uses the standard IServiceProvider at runtime.

What Scrutor Adds

Assembly scanning with Scrutor lets you register all types in one or more assemblies that match a predicate โ€” all implementations of a given interface, all classes with a specific attribute, or all types in a particular namespace โ€” in a single fluent call. This eliminates dozens of manual AddTransient<IMyService, MyServiceImpl>() lines as your service count grows.

Service decoration with Scrutor lets you wrap any registered service with a decorator without touching the original registration. This is the canonical way to apply cross-cutting concerns like caching, logging, or retry logic on top of a service boundary โ€” the Decorator pattern without the boilerplate of manually re-registering the inner implementation.

Where Scrutor Falls Short

Scrutor does not add a new container. Every registration still goes through MEDI, which means all the underlying container limitations remain: no property injection, no interception, no child scopes. Scrutor is best understood as a productivity layer โ€” it makes registering and decorating services easier, but it does not change the fundamental capability boundary of the container.


What Is Autofac?

Autofac is a mature, full-featured IoC container for .NET. Unlike Scrutor, Autofac replaces the built-in MEDI container at the IServiceProvider level using an adapter. You register services via Autofac's ContainerBuilder (and still support MEDI registrations through Populate()), and at runtime all resolutions go through Autofac's own resolver instead of MEDI's.

This architectural difference is significant. Autofac is a different engine, not a skin over the existing one.

What Autofac Adds

Property injection is one of Autofac's most requested capabilities. MEDI resolves dependencies only through constructors; Autofac can inject into properties and methods, which is essential when working with legacy codebases or frameworks that expect property-injected services.

Modules are Autofac's answer to registration organisation. A module is a class that encapsulates a related set of registrations โ€” you compose your container from modules, which keeps registration logic close to the services it registers rather than scattered across a monolithic Program.cs.

Interception allows you to wrap service resolutions with dynamic proxies at the container level, using Castle DynamicProxy. This enables AOP-style cross-cutting concerns โ€” logging, caching, retry โ€” without modifying the service classes or their call sites.

Child lifetime scopes give you the ability to create nested resolution contexts with their own service overrides, useful in multi-tenant or plugin architectures where different scopes require different service instances.

Named and keyed services existed in Autofac long before .NET 8 added keyed services to MEDI, and Autofac's implementation is more flexible โ€” you can resolve named services via parameter matching, delegate factories, or index-based resolution.

Where Autofac Falls Short

Autofac introduces real costs. The learning curve is steeper. Debugging registration errors is harder because Autofac's exception messages are less familiar to .NET developers accustomed to MEDI. Replacing the runtime container can cause subtle compatibility issues with some NuGet packages that depend on MEDI-specific behaviours. And for teams already fluent in MEDI, the switching cost is non-trivial โ€” both in migration effort and in the cognitive overhead of maintaining a different mental model for service resolution.

For most microservices or focused APIs, Autofac is more power than you need. The complexity it introduces frequently exceeds the problems it solves.


Side-by-Side Comparison

Feature MEDI Scrutor Autofac
Assembly scanning Manual โœ… Fluent API โœ… Native
Service decoration Manual โœ… Decorate<>() โœ… Native
Property injection โŒ โŒ โœ…
Constructor injection โœ… โœ… โœ…
Named / keyed services โœ… (.NET 8+) โŒ โœ… (richer)
Interception (AOP) โŒ โŒ โœ… (via DynamicProxy)
Child lifetime scopes โŒ โŒ โœ…
Modules โŒ โŒ โœ…
Replaces MEDI runtime No No Yes
Performance overhead Lowest Minimal Moderate
Learning curve Low Low High
ASP.NET Core integration Native Native Via adapter

When Should You Use Microsoft.Extensions.DI Alone?

Use MEDI as your sole container when your application is a straightforward API or microservice with fewer than 50-100 registered services, no cross-cutting decoration requirements, and no plugin architecture. For green-field ASP.NET Core applications starting in 2026, the combination of MEDI's built-in keyed services (available since .NET 8) and well-organised extension methods can comfortably handle most registration patterns.

If your service registrations can be grouped into clearly named extension methods on IServiceCollection โ€” AddApplicationServices(), AddInfrastructureServices() โ€” and your team does not need decoration or scanning, MEDI gives you the fastest path to a working, debuggable, zero-overhead DI setup.

The course's Chapter 3 covers how to structure EF Core and repository registrations cleanly in MEDI โ€” the same approach that keeps large APIs manageable without reaching for a third-party container. If you want to see how this scales in a full production API, Chapter 3 of the ASP.NET Core Web API: Zero to Production course shows the patterns in context.


When Should You Add Scrutor to MEDI?

Add Scrutor when you find yourself writing repetitive assembly-scanning loops or manual decorator wrappers. The two most common trigger points are:

Growing service count โ€” you have more than 20-30 implementations of a common interface (commands, handlers, repositories, validators) and manually registering each one is error-prone and tedious.

Decorator pattern adoption โ€” your team has decided to use the Decorator pattern for cross-cutting concerns (logging, caching, retry at the service boundary), and you want a clean registration model rather than wrapping manually.

Scrutor's key advantage is that it is additive: you keep the MEDI runtime, retain full compatibility with the rest of the .NET ecosystem, and add only the registration conveniences you need. The cost is near-zero, the compatibility risk is negligible, and most teams find it pays off after the third time they need to scan an assembly.

This is the right choice for the majority of enterprise ASP.NET Core teams in 2026.


When Should You Use Autofac?

Use Autofac in three specific scenarios:

Migrating a legacy .NET Framework application where property injection is already in use throughout a large existing codebase. Refactoring to constructor injection at scale is often not feasible, and Autofac smooths the migration path.

Plugin and modular architectures that require child lifetime scopes โ€” situations where different parts of your application need to resolve different service implementations for the same interface at the same time, isolated from each other.

AOP-heavy designs where your team has made a conscious decision to apply cross-cutting concerns through dynamic proxies at the container level rather than at the service level. This is rare in modern .NET design, but Autofac handles it better than any alternative.

For new projects, the bar for introducing Autofac should be high. The compatibility overhead, learning curve, and additional failure surface are real costs. If your use case is solely assembly scanning or service decoration, Scrutor solves it with far less complexity.


What Is the Right Default for Most Teams in 2026?

For most enterprise .NET teams building ASP.NET Core APIs in 2026, the answer is: start with MEDI, add Scrutor if you need scanning or decoration, and only adopt Autofac if you genuinely hit one of the specific advanced scenarios it uniquely solves.

This is not a "pick the boring default" argument. It is a recognition that Autofac solves problems that modern .NET has progressively addressed โ€” keyed services, better scoping, improved MEDI diagnostics โ€” making the gap narrower each release cycle. The scenarios where Autofac is the correct choice are real but specific, and should be reached deliberately rather than defaulted to.


Anti-Patterns to Avoid

Using Autofac for assembly scanning alone. Scrutor does this with no container swap required. Replacing the entire runtime container for a registration convenience is disproportionate.

Using Scrutor to replace constructor injection discipline. Scanning assemblies is not a substitute for thinking clearly about service design. Teams that use scanning aggressively sometimes lose visibility into what is actually registered.

Using MEDI alone for complex modular monoliths. If your application has 10 modules each with their own registration requirements, structure your MEDI registrations into well-named extension methods or modules from day one. This scales further than most teams expect.

Mixing Autofac and MEDI registration logic without a clear convention. When both are in play, some services come from MEDI and some from Autofac's builder. Teams that do not document this distinction end up with registration bugs that are hard to trace.


โ˜• Prefer a one-time tip? Buy us a coffee โ€” every bit helps keep the content coming!


FAQ

What is the difference between Scrutor and Autofac in .NET?

Scrutor extends the built-in Microsoft.Extensions.DependencyInjection container with assembly scanning and service decoration. It does not replace the container. Autofac is a separate IoC container that replaces MEDI's runtime entirely via an adapter, adding property injection, interception, modules, child scopes, and richer registration APIs.

Should I use Autofac in a new ASP.NET Core 10 project?

For most new projects, no. ASP.NET Core's built-in DI container handles the vast majority of scenarios well, and Autofac introduces non-trivial complexity, a steeper learning curve, and compatibility considerations. Only adopt Autofac if you need property injection, dynamic proxies for AOP, or child lifetime scopes โ€” scenarios that are genuinely uncommon in greenfield microservices.

Does Scrutor replace the DI container in ASP.NET Core?

No. Scrutor adds extension methods to IServiceCollection and uses the standard MEDI runtime at resolution time. It is a registration helper, not a replacement container. This means no compatibility risk and negligible performance overhead compared to Autofac.

What are keyed services in .NET 8 and do they replace Autofac's named services?

Keyed services, introduced in .NET 8, allow you to register and resolve multiple implementations of the same interface by a string or enum key. They cover many of the scenarios previously requiring Autofac's named/keyed registration. However, Autofac's named service support remains more flexible โ€” supporting delegate factories, index-based resolution, and parameter matching โ€” which matters in complex plugin architectures.

Can I use Scrutor and Autofac together?

You can, but it is rarely useful. When Autofac is your container, it provides its own assembly scanning (RegisterAssemblyTypes) that is at least as powerful as Scrutor. Using Scrutor on top of an Autofac-backed IServiceCollection adds complexity without meaningful benefit.

What is assembly scanning in dependency injection?

Assembly scanning is the practice of automatically registering services by inspecting assemblies at startup using reflection โ€” finding all classes that implement a given interface or match a predicate โ€” instead of manually calling AddTransient<IFoo, Foo>() for each one. Scrutor's Scan() method and Autofac's RegisterAssemblyTypes() both implement this pattern.

When is property injection a valid reason to use Autofac?

Property injection is valid in legacy codebases where constructor injection cannot be applied uniformly โ€” typically in large .NET Framework-to-.NET Core migrations where base classes, MVC filters, or framework-managed objects cannot have their constructors modified. For new code, constructor injection is always preferable because dependencies are explicit and testable.


For more .NET architecture deep-dives, visit Coding Droplets and subscribe to the YouTube channel for video walkthroughs of production patterns.