DEV Community

Hootan Hemmati
Hootan Hemmati

Posted on

Elevating Dependency Injection in .NET with Scrutor and Autofac

As .NET developers, we're all familiar with the challenges of managing dependency injection (DI) in large projects. When the number of services and repositories grows, manually registering each one can become a time-consuming and tedious task. Fortunately, there are solutions that make this process simple and elegant: Scrutor and Autofac!

In my recent project, I needed to inject numerous services and repositories located across different class libraries effortlessly. By leveraging Scrutor, I managed to handle all these dependencies with just a few lines of code.

Let's dive into the code and explain each method:

services.Scan(current => current
    .FromAssemblies(typeof(Services.Service1).GetTypeInfo().Assembly)
    .AddClasses(theClass => theClass.InExactNamespaceOf<Services.Service1>())
    // For Service4 and Service5
    .AsSelf()
    // For Service1, Service2, Service3
    .AsImplementedInterfaces()
    .WithSingletonLifetime()

    .FromAssemblies(typeof(Repositories.Repository1).GetTypeInfo().Assembly)
    .AddClasses(theClass => theClass.InExactNamespaceOf<Repositories.Repository1>())
    // For Repository4 and Repository5
    .AsSelf()
    // For Repository1, Repository2, Repository3
    .AsImplementedInterfaces()
    .WithTransientLifetime()
);
Enter fullscreen mode Exit fullscreen mode

Explanation of the methods and their purpose:

  1. services.Scan(...): This method initiates the scanning and automatic registration of dependencies. It allows us to specify the assemblies and classes we want to scan.

  2. FromAssemblies(...): Here, we tell Scrutor which assemblies to scan. By using typeof(Services.Service1).GetTypeInfo().Assembly, we're specifying the assembly that contains our services.

  3. AddClasses(...): This method determines which classes should be registered. The InExactNamespaceOf<Services.Service1>() directive tells Scrutor to include only the classes in the exact namespace of Service1.

  4. AsSelf(): Registers the classes as themselves. For example, if we have a class named Service4, we can inject it as Service4.

  5. AsImplementedInterfaces(): Registers the classes as the interfaces they implement. This is useful when we want to use interfaces for dependency injection.

  6. WithSingletonLifetime() and WithTransientLifetime(): These methods set the lifetime of the dependencies. Singleton means a single instance of the service exists throughout the application's lifetime, while Transient creates a new instance for each request.

Why Scrutor?

  • Simplified Dependency Injection: Eliminates the need to manually register each service and repository.
  • High Flexibility: Allows precise determination of classes, interfaces, and lifetimes.
  • Assembly Scanning Capability: You can scan classes from various assemblies and namespaces.

Introducing Autofac and Comparing it with Scrutor

But Scrutor isn't our only option. Autofac is another powerful library for managing dependency injection in .NET, offering advanced features.

What is Autofac?

Autofac is an Inversion of Control (IoC) container that provides developers with flexible and powerful ways to manage their dependencies. With Autofac, we can have greater control over how dependencies are created and injected.

Key Features of Autofac:

  • Modularity: Ability to partition dependency registrations into separate modules for better organization.
  • Precise Lifetime Control: Advanced options for setting dependency lifetimes, such as InstancePerDependency, SingleInstance, InstancePerLifetimeScope, etc.
  • Support for AOP (Aspect-Oriented Programming): Allows the use of interceptors to add extra behaviors to services.
  • Integration with Various Frameworks: Supports ASP.NET Core, WCF, Web API, and more.

How to Use Autofac:

  1. Install Autofac: First, install the Autofac NuGet packages and its ASP.NET Core integration.

  2. Setup in Startup.cs:

public IServiceProvider ConfigureServices(IServiceCollection services)
{
    // Register default services
    services.AddControllers();

    // Create a ContainerBuilder
    var builder = new ContainerBuilder();

    // Transfer default registrations to Autofac
    builder.Populate(services);

    // Register dependencies
    builder.RegisterType<MyService>().As<IMyService>().InstancePerLifetimeScope();

    // Build the container
    var container = builder.Build();

    // Return the IServiceProvider from Autofac
    return new AutofacServiceProvider(container);
}
Enter fullscreen mode Exit fullscreen mode
  1. Using Modules:

You can organize your dependencies into modules:

public class ServiceModule : Module
{
    protected override void Load(ContainerBuilder builder)
    {
        builder.RegisterType<Service1>().As<IService1>();
        builder.RegisterType<Service2>().As<IService2>();
    }
}
Enter fullscreen mode Exit fullscreen mode

Then, register the module in ConfigureServices:

builder.RegisterModule(new ServiceModule());
Enter fullscreen mode Exit fullscreen mode

Comparing Scrutor and Autofac:

Feature Scrutor Autofac
Simplicity Simple and lightweight, ideal for auto-registering dependencies Powerful but with added complexity
Lifetime Control Basic control with With...Lifetime() methods Advanced control with various lifetime scopes
Modularity Not available Supports modules for better organization
AOP Support Limited support Strong support for interceptors and AOP
Integration Uses default DI container of ASP.NET Core Replaces default container with Autofac

Which One to Choose?

  • Scrutor is ideal for projects that want to simplify dependency registration using the default DI container of ASP.NET Core without adding extra complexity.
  • Autofac is suitable for larger, more complex projects that require finer control and advanced features in dependency management.

Conclusion

Both libraries are powerful tools for managing dependency injection in .NET. Your choice between them depends on your project's needs and the level of control you require. If you're looking for simplicity and speed, Scrutor is an excellent option. But if you need more advanced features, Autofac can meet your demands.

Ultimately, our main goal is to improve code structure, enhance maintainability, and accelerate development. So choose the right tool carefully and enjoy its benefits.

Top comments (0)