Scrutor Vs Autofac In C#: What You Need To Know
Tags: webdev, programming, dotnet, coding
Published: 2024-02-29 17:00:00

The post [Scrutor vs Autofac in C#: What You Need To Know](https://www.devleader.ca/2024/02/23/scrutor-vs-autofac-in-c-what-you-need-to-know/) appeared first on [Dev Leader](https://www.devleader.ca).

Let’s explore two popular dependency injection frameworks for dotnet as we compare Scrutor vs Autofac in C#! Dependency injection becomes (almost) a necessity as your application grows in size and complexity, and having the right dependency injection framework to use can make a world of difference.

Starting with a brief explanation of what dependency injection is in C#: Dependency injection is a design approach that allows objects to be loosely coupled and promotes the concept of passing in (or “injecting”) dependencies rather than directly creating them within a class. This promotes modularity, testability, and flexibility in your codebase.

So why is it important to choose the right dependency injection framework for your C# projects? Well, the right framework can greatly simplify your codebase, improve maintainability, and enhance the overall performance of your application. Scrutor and Autofac are two popular options to consider, and in this article, we’ll compare and analyze them in detail.

---

## Overview of Scrutor and Autofac

Scrutor and Autofac are both popular dependency injection frameworks in the C# ecosystem. They provide developers with the tools to effectively manage dependencies and promote modular and extensible software architectures (and we love that kind of stuff around here!). In this section, I’ll provide a brief introduction to both Scrutor and Autofac to kick us off in our comparison.

### Scrutor in CSharp

Scrutor is a lightweight, convention-based assembly scanning extension for [the default .NET Core DI container](https://www.devleader.ca/2024/02/21/iservicecollection-in-c-simplified-beginners-guide-for-dependency-injection/). It simplifies the registration of services by allowing developers to use attribute-based conventions rather than explicit registrations. With Scrutor, you can define rules and patterns that automatically discover and register types based on specific attributes or naming conventions.

Some key advantages of Scrutor include:

1. Simplicity: Scrutor offers a simple and intuitive API that makes it easy to configure and use. It simplifies the process of registering services by leveraging conventions, reducing the need for manual registrations.
    
2. Flexibility: Scrutor allows for dynamic composition and discovery of services based on conventions. This flexibility enables developers to easily extend and modify their software architecture without the need to rewrite or modify existing code.
    
3. Performance: Scrutor is designed to be highly performant, with minimal impact on the overall application performance. By leveraging fast assembly scanning techniques, it ensures efficient service registration and resolution.
    

### Autofac in CSharp

[Autofac is a powerful and feature-rich DI container for .NET applications](https://www.devleader.ca/2023/08/22/dependency-injection-how-to-start-with-autofac-the-easy-way/), and historically, this has been my go-to for dependency injection. It provides advanced capabilities and extensive configurability, making it suitable for complex projects. Autofac offers a ton of features and extensions that enable developers to achieve fine-grained control over dependency injection, but that might also make it overly complicated for many use-cases.

Some key advantages of Autofac include:

1. Extensibility: Autofac provides a modular and extensible architecture, allowing developers to customize and extend its behavior to meet specific requirements. It offers a wide range of extension points and integration options, making it highly adaptable to different project needs.
    
2. Lifetime Management: Autofac offers various options for managing the lifetime of registered services, including singleton, per request, and per dependency. This flexibility allows for efficient resource utilization and enables developers to control the lifespan of dependencies.
    
3. Interoperability: Autofac seamlessly integrates with other popular frameworks and technologies in the .NET ecosystem. Whether you are developing ASP.NET Core applications or working with third-party libraries, Autofac provides seamless integration capabilities, ensuring a smooth development experience.
    

Scrutor and Autofac are both great options for [dependency injection in C# applications](https://www.devleader.ca/2024/01/07/what-is-inversion-of-control-a-simplified-beginners-guide/). Scrutor offers a lightweight and convention-based approach, simplifying service registration, while Autofac provides extensive configurability and advanced features for complex projects. Depending on the specific needs and complexity of your project, you can choose the framework that best suits your requirements — there is no universal “best” here.

---

## Key Differences of Scrutor vs Autofac in CSharp

When comparing Scrutor and Autofac for dependency injection in C#, there are several key differences to consider. In this section, we’ll explore these differences in terms of key features, syntax, and usage, as well as their approach to registration and resolving dependencies.

### Key Features of these Frameworks

Generally speaking, Scrutor is a lightweight library that offers a simple and intuitive way to scan assemblies and apply conventions for dependency registration. It provides powerful filtering capabilities, allowing developers to easily specify which types should be included or excluded during the scanning process. But the real benefit, in my opinion, is in the simplicity and the fact it works with IServiceCollection seamlessly.

On the other hand, Autofac is a more robust and feature-rich dependency injection container. It offers more advanced features such as instance scopes, lifetime management, interception, module system, and integration with other frameworks. That means also the IServiceCollection we get in ASP.NET Core apps — but I admit it feels a bit more clunky.

### Differences in Syntax and Usage

When it comes to syntax and usage, both Scrutor and Autofac provide clean and concise APIs for registering and resolving dependencies. However, they differ in their approach.

Scrutor leverages the power of LINQ expressions to define conventions for dependency scanning and registration. It allows developers to specify rules for identifying types based on naming conventions, interfaces implemented, attributes applied, or any custom criteria. This makes it easy to quickly set up and automate the registration process without writing explicit code for each dependency.

Autofac, on the other hand, uses a more traditional and explicit syntax for registration. Developers need to explicitly specify the mapping between interfaces and concrete implementations using its fluent registration API. While this requires more manual setup compared to Scrutor’s convention-based approach, it offers more control and flexibility for complex scenarios.

I’ve found that I’ve had to create my own [dependency scanning solutions for Autofac](https://www.devleader.ca/2023/09/17/automatic-module-discovery-with-autofac-simplified-registration/), although they’re very straightforward with some reflection. You can see how I [manage dependency scanning for Autofac in this video](https://www.youtube.com/watch?v=L8KeFxUWaGM):

{% embed https://www.youtube.com/watch?v=L8KeFxUWaGM %}

---

## Code Examples: Using Scrutor for Dependency Injection in CSharp

In this section, I’ll provide you with code examples and a step-by-step guide on how to use Scrutor for dependency injection in C#. Of course, this will be a contrived example so you’ll want to tailor the concepts here to be applicable to \*your\* situation. As much as I want to provide you with copy+paste code, I can’t possibly know everyone’s application structure. You’ve been warned!

### 1 – Installing Scrutor in CSharp

To begin, make sure you have Scrutor installed in your project. You can do this by adding the `Scrutor` NuGet package to your solution. At the time of writing, [4.2.2 is the latest available version of Scrutor](https://www.nuget.org/packages/Scrutor). You can of course find more information about Scrutor in C# before diving too far in by [checking out the GitHub for it](https://github.com/khellang/Scrutor).

### 2 – Setting Up The Dependency Container for Scrutor in CSharp

First, let’s start by setting up the DI container in your application’s startup class. Here’s an example using the default DI container in ASP.NET Core:

```csharp
using Microsoft.Extensions.DependencyInjection;
using Scrutor;

public class Startup
{
    public void ConfigureServices(IServiceCollection services)
    {
        services.Scan(scan => scan
            .FromAssemblyOf<Startup>()
            .AddClasses()
            .AsMatchingInterface()
            .WithScopedLifetime()
        );

        // Add other services and configurations here
    }
}
```

In the above code, `services.Scan` is used to scan the assemblies and register the types with their corresponding interfaces. The `FromAssemblyOf<Startup>` method specifies which assembly to scan. The `AddClasses()` method selects all classes to be registered, and the `AsMatchingInterface()` method specifies that each class should be registered with its matching interface. Finally, the `WithScopedLifetime()` method specifies the lifetime of the services to be scoped.

### 3 – Example Service in Our Application

Let’s continue by creating an example interface and its corresponding implementation. Assuming we have an `IEmailService` interface and the `EmailService` class implementing it:

```csharp
public interface IEmailService
{
    void SendEmail(string recipient, string message);
}

public class EmailService : IEmailService
{
    public void SendEmail(string recipient, string message)
    {
        // Code to send email
    }
}
```

### 4 – Consuming Registered Services with Scrutor

Now, we can consume the registered services using constructor injection. Let’s assume we have a `HomeController`, which requires an `IEmailService`:

```csharp
public class HomeController : Controller
{
    private readonly IEmailService _emailService;

    public HomeController(IEmailService emailService)
    {
        _emailService = emailService;
    }

    public IActionResult Index()
    {
        // Use the email service to send emails
        _emailService.SendEmail("example@example.com", "Hello, Scrutor!");

        return View();
    }
}
```

In the above code, the `HomeController` class has a constructor that takes in an `IEmailService` dependency. The DI container takes care of injecting the `EmailService` implementation when the `HomeController` is instantiated.

---

## Code Examples: Using Autofac for Dependency Injection in CSharp

In this section, I’ll provide a step-by-step guide on how to use Autofac for dependency injection in C#. I’ll include code snippets and explanations to help you understand the process.

### 1 – Installing Autofac

Before we can start using Autofac for dependency injection, we need to install the necessary packages. Open your project in Visual Studio and navigate to the NuGet Package Manager. Search for “Autofac” and install the package.

### 2 – Setting up the Container in Autofac

Once the package is installed, we can start setting up the Autofac container. The container is responsible for managing and resolving dependencies in our application. In your project, open the `Startup.cs` or similar file where you configure your services.

First, add the necessary namespaces at the top of the file:

```csharp
using Autofac;
using Autofac.Extensions.DependencyInjection;
```

Next, create a method to configure the Autofac container:

```csharp
public IServiceProvider ConfigureServices(IServiceCollection services)
{
    var builder = new ContainerBuilder();

    // Add your services and dependencies here

    builder.Populate(services);

    var container = builder.Build();

    return new AutofacServiceProvider(container);
}
```

In the `ConfigureServices` method, create an instance of the `ContainerBuilder` class. This class will be used to register your services and dependencies. Populate the container with the services from the `services` parameter, and then build the container.

Finally, return a new instance of the `AutofacServiceProvider` class, passing in the container as a parameter.

### 3 – Registering Services in Autofac

With the container set up, we can now register our services and dependencies. In the `ConfigureServices` method, you can use the `builder` instance to register your services.

Here’s an example registering a service with a single implementation:

```csharp
builder.RegisterType<MyService>().As<IMyService>();
```

In this example, we register `MyService` as the implementation of `IMyService`. This means that whenever `IMyService` is requested, Autofac will provide an instance of `MyService`.

You can also register multiple implementations of an interface using the `RegisterType` method:

```csharp
builder.RegisterType<MyService1>().As<IMyService>();
builder.RegisterType<MyService2>().As<IMyService>();
```

In this case, there are two implementations of `IMyService`, `MyService1` and `MyService2`. Whenever `IMyService` is requested, Autofac will provide an instance of either `MyService1` or `MyService2`.

### 4 – Resolving Dependencies in Autofac

Now that our services are registered, we can resolve them using the Autofac container. In your classes where you need to use a dependency, you can add a constructor parameter of the dependency type.

```csharp
public class MyController
{
    private readonly IMyService _myService;

    public MyController(IMyService myService)
    {
        _myService = myService;
    }

    // Use _myService in your methods
}
```

In this example, `MyController` depends on `IMyService`. By adding it as a constructor parameter, Autofac will automatically resolve and provide an instance of `IMyService` when creating a new instance of `MyController`.

---

## Modular CSharp Application with Plugin Support

In a modular C# application with plugin support, dependency injection becomes vital for integrating and managing plugins seamlessly. It’s difficult for me to imagine how someone might need to either manually wire these types of things up, or roll their own type of dependency/plugin loading system… especially when these things work so well out-of-the-box! Let’s see how Scrutor and Autofac can be applied to handle this scenario effectively.

### Code Example: Using Scrutor in CSharp to Scan

With Scrutor, we can use the `Assemblies.FromPath` method to scan and register assemblies dynamically. This enables us to discover and register plugins at runtime.

```csharp
public void ConfigureServices(IServiceCollection services)
{
    services.Scan(scan => scan
        .FromAssembliesFromPath(
            AppDomain.CurrentDomain.BaseDirectory,
            "SomePluginAssemblies")
        .AddClasses()
        .AsImplementedInterfaces()
        .WithTransientLifetime());
}
```

### Code Example: Using Autofac in CSharp to Scan

Autofac provides a similar capability with its `AssemblyFinder` class, allowing us to scan and register assemblies dynamically. We can use the `RegisterAssemblyTypes` method to achieve this.

```csharp
public void ConfigureContainer(ContainerBuilder builder)
{
    var assemblyFinder = new AssemblyFinder();
    var pluginAssemblies = assemblyFinder.GetAssembliesInFolder("SomePluginAssemblies");

    builder.RegisterAssemblyTypes(pluginAssemblies)
        .AsImplementedInterfaces()
        .InstancePerLifetimeScope();
}
```

---

## Wrapping Up Scrutor vs Autofac in CSharp

Throughout this article, we looked at a comparison of Scrutor and Autofac in C# with the goal of understanding the differences between these two dependency injection frameworks in C#. We explored their features, advantages, and use cases through code examples to give readers a clear understanding of how they work in practice.

When choosing between Scrutor vs Autofac in C#, it is important to consider factors such as project complexity, performance needs, community support, and personal familiarity with the frameworks. Scrutor’s simplicity and flexibility make it a good choice for small to medium-sized projects or situations where rapid development and convention-based registration are preferred. Autofac, with its advanced features and mature ecosystem, is well-suited for complex enterprise-level applications that require extensive customization and fine-grained control over the dependency injection process.

In the end, you’ll want to work with your team to decide what’s a better fit. But either of these two options is likely going to be better than no dependency injection at all! If you found this useful and you’re looking for more learning opportunities, consider [subscribing to my free weekly software engineering newsletter](https://subscribe.devleader.ca) and check out my [free videos on YouTube](https://www.youtube.com/@devleader?sub_confirmation=1)!

---

## Want More Dev Leader Content?

* Follow along on this platform if you haven’t already!    
* Subscribe to my free weekly software engineering and dotnet-focused newsletter. I include exclusive articles and early access to videos:  
    [**SUBSCRIBE FOR FREE**](https://subscribe.devleader.ca/)    
* Looking for courses? Check out my offerings:  
    [**VIEW COURSES**](https://devleader.ca/courses)    
* E-Books & other resources:  
    [**VIEW RESOURCES**](https://products.devleader.ca/)    
* Watch hundreds of full-length videos on my YouTube channel:  
    [**VISIT CHANNEL**](https://youtube.com/@devleader?sub_confirmation=1)    
* Visit my website for hundreds of articles on various software engineering topics (including code snippets):  
    [**VISIT WEBSITE**](https://devleader.ca/)    
* Check out the repository with many code examples from my articles and videos on GitHub:  
    [**VIEW REPOSITORY**](https://github.com/ncosentino/DevLeader)