.NET HELP

Autofac .NET 6 (How It Works For Developers)

Published July 1, 2024
Share:

In the realm of .NET development, managing dependencies efficiently is crucial for building scalable, maintainable, and testable applications. Dependency injection (DI) containers play a pivotal role in achieving these goals by facilitating the inversion of control (IoC) principle. Among the plethora of generic hosting mechanism libraries available, Autofac stands out as a feature-rich and extensible framework for .NET.

In this article, we'll embark on a journey to explore Autofac .NET 6, unraveling its features and benefits to showcase practical examples of its usage. Later in this article, we will learn about IronPDF, a PDF generation library from Iron Software. We will also present a use case where Autofac.NET and IronPDF are used together.

Understanding Autofac .NET

Autofac is an open-source IoC container for .NET that provides comprehensive support for dependency injection and component registration in apps like web APIs. Developed by Nicholas Blumhardt and maintained by a dedicated community, Autofac offers a robust and flexible solution for managing object lifetimes, resolving dependencies, and composing application components.

Features of Autofac

  1. Container Building and Component Registration: You can build containers using Autofac by registering components in the startup class. You can register components using lambdas, types, or pre-built instances.

    public class Startup
    {
        public void ConfigureContainer()
        {
            var builder = new ContainerBuilder(); // host sub property builder
            builder.RegisterInstance(new TaskRepository()).As<ITaskRepository>();
            builder.RegisterType<TaskController>();
            builder.Register(c => new LogManager(DateTime.Now)).As<ILogger>();
            // Scan an assembly for components
            builder.RegisterAssemblyTypes(myAssembly).Where(t => t.Name.EndsWith("Repository")).AsImplementedInterfaces();
            var container = builder.Build();
        }
    }
    public class Startup
    {
        public void ConfigureContainer()
        {
            var builder = new ContainerBuilder(); // host sub property builder
            builder.RegisterInstance(new TaskRepository()).As<ITaskRepository>();
            builder.RegisterType<TaskController>();
            builder.Register(c => new LogManager(DateTime.Now)).As<ILogger>();
            // Scan an assembly for components
            builder.RegisterAssemblyTypes(myAssembly).Where(t => t.Name.EndsWith("Repository")).AsImplementedInterfaces();
            var container = builder.Build();
        }
    }
    Public Class Startup
    	Public Sub ConfigureContainer()
    		Dim builder = New ContainerBuilder() ' host sub property builder
    		builder.RegisterInstance(New TaskRepository()).As(Of ITaskRepository)()
    		builder.RegisterType(Of TaskController)()
    		builder.Register(Function(c) New LogManager(DateTime.Now)).As(Of ILogger)()
    		' Scan an assembly for components
    		builder.RegisterAssemblyTypes(myAssembly).Where(Function(t) t.Name.EndsWith("Repository")).AsImplementedInterfaces()
    		Dim container = builder.Build()
    	End Sub
    End Class
    VB   C#
  2. Express Dependencies: Autofac can inject constructor parameters, handle property injection, and method injection.

    public class TaskController
    {
        private ITaskRepository _repository;
        private ILogger _logger;
    
        public TaskController(ITaskRepository repository, ILogger logger)
        {
            this._repository = repository;
            this._logger = logger;
        }
    }
    public class TaskController
    {
        private ITaskRepository _repository;
        private ILogger _logger;
    
        public TaskController(ITaskRepository repository, ILogger logger)
        {
            this._repository = repository;
            this._logger = logger;
        }
    }
    Public Class TaskController
    	Private _repository As ITaskRepository
    	Private _logger As ILogger
    
    	Public Sub New(ByVal repository As ITaskRepository, ByVal logger As ILogger)
    		Me._repository = repository
    		Me._logger = logger
    	End Sub
    End Class
    VB   C#
  3. Flexible Module System: Autofac modules strike a balance between XML configuration and code-based registrations. You can specify complex registrations in code or change deployment-time behavior using XML.

    public class CarTransportModule : Module
    {
        public bool ObeySpeedLimit { get; set; }
    
        protected override void Load(ContainerBuilder builder)
        {
            builder.RegisterType<Car>().As<IVehicle>();
            if (ObeySpeedLimit)
                builder.RegisterType<SaneDriver>().As<IDriver>();
            else
                builder.RegisterType<CrazyDriver>().As<IDriver>();
        }
    }
    public class CarTransportModule : Module
    {
        public bool ObeySpeedLimit { get; set; }
    
        protected override void Load(ContainerBuilder builder)
        {
            builder.RegisterType<Car>().As<IVehicle>();
            if (ObeySpeedLimit)
                builder.RegisterType<SaneDriver>().As<IDriver>();
            else
                builder.RegisterType<CrazyDriver>().As<IDriver>();
        }
    }
    Public Class CarTransportModule
    	Inherits Module
    
    	Public Property ObeySpeedLimit() As Boolean
    
    	Protected Overrides Sub Load(ByVal builder As ContainerBuilder)
    		builder.RegisterType(Of Car)().As(Of IVehicle)()
    		If ObeySpeedLimit Then
    			builder.RegisterType(Of SaneDriver)().As(Of IDriver)()
    		Else
    			builder.RegisterType(Of CrazyDriver)().As(Of IDriver)()
    		End If
    	End Sub
    End Class
    VB   C#
  4. Simple Extension Points: Autofac provides activation events to customize component activation or release.

    var builder = new ContainerBuilder();
    builder.RegisterType<Listener>().As<IListener>().OnActivated(e => e.Instance.StartListening());
    builder.RegisterType<Processor>().OnActivating(e => e.Instance.Initialize());
    var container = builder.Build();
    var builder = new ContainerBuilder();
    builder.RegisterType<Listener>().As<IListener>().OnActivated(e => e.Instance.StartListening());
    builder.RegisterType<Processor>().OnActivating(e => e.Instance.Initialize());
    var container = builder.Build();
    Dim builder = New ContainerBuilder()
    builder.RegisterType(Of Listener)().As(Of IListener)().OnActivated(Function(e) e.Instance.StartListening())
    builder.RegisterType(Of Processor)().OnActivating(Function(e) e.Instance.Initialize())
    Dim container = builder.Build()
    VB   C#

Key Features of Autofac.NET

  1. Flexible Component Registration: Autofac allows developers to register components using a variety of registration techniques, including manual registration, assembly scanning, and attribute-based registration. This flexibility enables fine-grained control over component instantiation and configuration.
  2. Lifetime Management: Autofac supports various object lifetime scopes, including singleton, instance per dependency, instance per lifetime scope, and instance per request. This granular control over object lifetimes ensures efficient resource utilization and prevents memory leaks in long-running applications.
  3. Automatic Dependency Resolution: Autofac automatically resolves dependencies based on the registered component registrations and their dependencies. This automatic wiring simplifies the configuration of complex object graphs and promotes loose coupling between components.
  4. Module Composition: Autofac allows developers to organize and encapsulate component registrations using modules. Modules serve as logical containers for related registrations, making it easier to manage and maintain large-scale applications with multiple components.
  5. Interception and AOP: Autofac provides support for interception and aspect-oriented programming (AOP) through its interception extension. With interception, developers can apply cross-cutting concerns such as logging, caching, and security to components without modifying their implementation.
  6. ASP.NET Core and .NET Core Integration: Autofac seamlessly integrates with .NET Core and ASP.NET Core, providing first-class support for dependency injection in modern web applications and microservices. It leverages the built-in service provider abstraction to ensure compatibility and interoperability with the .NET ecosystem.

Practical Examples with Autofac.NET

Let's explore some practical examples to illustrate the usage of Autofac.NET:

public class Program
{
    public static void Main()
    {
        // Setting up Autofac container
        var builder = new ContainerBuilder();
        // Registering types manually
        builder.RegisterType<MyService>().As<IMyService>();
        // Registering types using assembly scanning
        builder.RegisterAssemblyTypes(typeof(MyAssembly).Assembly)
            .Where(t => t.Name.EndsWith("Repository"))
            .AsImplementedInterfaces();
        // Registering modules
        builder.RegisterModule(new MyModule());
        // Building the container
        var container = builder.Build();
        // Resolving dependencies
        using (var scope = container.BeginLifetimeScope())
        {
            var service = scope.Resolve<IMyService>();
            service.DoSomething();
        }
    }
}
public class Program
{
    public static void Main()
    {
        // Setting up Autofac container
        var builder = new ContainerBuilder();
        // Registering types manually
        builder.RegisterType<MyService>().As<IMyService>();
        // Registering types using assembly scanning
        builder.RegisterAssemblyTypes(typeof(MyAssembly).Assembly)
            .Where(t => t.Name.EndsWith("Repository"))
            .AsImplementedInterfaces();
        // Registering modules
        builder.RegisterModule(new MyModule());
        // Building the container
        var container = builder.Build();
        // Resolving dependencies
        using (var scope = container.BeginLifetimeScope())
        {
            var service = scope.Resolve<IMyService>();
            service.DoSomething();
        }
    }
}
Public Class Program
	Public Shared Sub Main()
		' Setting up Autofac container
		Dim builder = New ContainerBuilder()
		' Registering types manually
		builder.RegisterType(Of MyService)().As(Of IMyService)()
		' Registering types using assembly scanning
		builder.RegisterAssemblyTypes(GetType(MyAssembly).Assembly).Where(Function(t) t.Name.EndsWith("Repository")).AsImplementedInterfaces()
		' Registering modules
		builder.RegisterModule(New MyModule())
		' Building the container
		Dim container = builder.Build()
		' Resolving dependencies
		Using scope = container.BeginLifetimeScope()
			Dim service = scope.Resolve(Of IMyService)()
			service.DoSomething()
		End Using
	End Sub
End Class
VB   C#

In this section, we've demonstrated the practical implementation of Autofac.NET for dependency injection. From manual registration to assembly scanning and module-based registration, we've shown the flexibility Autofac offers in managing dependencies. By utilizing these techniques, developers can streamline their application's dependency injection process, enhancing maintainability and scalability.

Benefits of Using Autofac.NET

  1. Simplicity and Flexibility: Autofac offers a simple and intuitive API for registering and resolving components, making dependency injection easy to implement and maintain.
  2. Testability and Maintainability: By promoting loose coupling and dependency inversion, Autofac enhances the testability and maintainability of .NET applications, enabling unit testing and refactoring with ease.
  3. Performance and Scalability: Autofac's lightweight and efficient runtime performance makes it suitable for high-performance applications and scalable systems with large object graphs.
  4. Extensibility and Customization: Autofac's extensible architecture allows developers to extend and customize Autofac's behavior through custom modules, registration sources, and middleware components, catering to diverse application requirements.
  5. Community and Support: With an active community of developers and comprehensive documentation, Autofac provides excellent support and resources for learning, troubleshooting, and contributing to the framework.

Autofac License

Autofac comes with an MIT License which is free for use for development and commercial purposes.

Introducing IronPDF from Iron Software

Autofac .NET 6 (How It Works For Developers): Figure 1 - IronPDF webpage

IronPDF is a robust C# PDF library designed to provide a comprehensive solution for managing PDFs in .NET projects. Whether your needs involve creating, editing, exporting, securing, loading, or manipulating PDF documents, IronPDF has the tools you need. Here are some of its standout features and applications:

Key Features

  • HTML to PDF Conversion: Effortlessly convert HTML content to PDF. Generate PDFs from HTML, MVC, ASPX, and images.
  • PDF Management: With over 50 features, IronPDF allows you to sign, edit, and extract content from PDFs, making digital signatures and modifications easy.
  • Cross-Platform Support: Compatible with C#, F#, and VB.NET, IronPDF runs on various .NET versions, including .NET Core, .NET Standard, and .NET Framework. It's also available for Java, Node.js, and Python.

Compatibility and Environments

  • .NET Versions: Supports C#, VB.NET, and F#.
  • Project Types: Suitable for web (Blazor & WebForms), desktop (WPF & MAUI), and console applications.
  • App Environments: Compatible with Windows, Linux, Mac, Docker, Azure, AWS, and more.
  • IDEs: Seamlessly integrates with Microsoft Visual Studio and JetBrains Rider.
  • OS & Processors: Operates on Windows, Mac, and Linux (x64, x86, ARM).

PDF Standards and Editing

  • Compatibility: Supports various PDF versions (1.2 - 1.7), PDF/UA, and PDF/A.
  • Customization: Set properties, security, and compression for PDF files.
  • Metadata and Structure: Edit metadata, revision history, and document structure.
  • Templates and Settings: Apply page templates, headers, footers, and page settings.

Performance Optimization

  • Efficiency: Full multithreading and async support for efficient PDF generation.
  • Priority: Focuses on accuracy, ease of use, and speed.

Now let's see a practical example with these two libraries.

Generate PDF Document Using Autofac.NET and IronPDF

First, let's create a Visual Studio console application

Autofac .NET 6 (How It Works For Developers): Figure 2 - Creating a Visual Studio console app

Provide the project name and location.

Autofac .NET 6 (How It Works For Developers): Figure 3 - Configure project details

For the next step, select the required .NET version and click Create.

Then install the IronPDF library from NuGet Package from Visual Studio Package Manager

Autofac .NET 6 (How It Works For Developers): Figure 4 - Installing the necessary IronPDF package

Install Autofac from NuGet Package from Visual Studio Package Manager

Autofac .NET 6 (How It Works For Developers): Figure 5 - Installing the necessary Autofac package

Code Example: Autofac and IronPDF

using Autofac;
using CacheManager.Core;
using IronPdf;
using System.Reflection;

namespace IronPdfDemos
{
    public class AutoFac
    {
        public static void Execute()
        {
            // Instantiate Cache and ChromePdfRenderer
            var renderer = new ChromePdfRenderer();
            var cache = CacheFactory.Build("ironPdfAutofac", settings =>
            {
                settings.WithDictionaryHandle();
            });

            // Prepare HTML content
            var content = "<h1>Demonstrate Autofac with IronPDF</h1>";
            content += "<p>This is an illustration of using Autofac for dependency injection and IronPDF for generating PDF documents.</p>";
            content += "<h2>Setting up Autofac container</h2>";

            // Setting up Autofac container
            var builder = new ContainerBuilder();
            content += "<p>var builder = new ContainerBuilder();</p>";

            content += "<h2>Registering types manually</h2>";
            // Registering types manually
            builder.RegisterType<MyService>().As<IMyService>();
            content += "<p>builder.RegisterType<MyService>().As<IMyService();</p>";

            content += "<h2>Registering types using assembly scanning</h2>";
            // Registering types using assembly scanning
            builder.RegisterAssemblyTypes(typeof(AutoFac).Assembly)
                .Where(t => t.Name.EndsWith("Repository"))
                .AsImplementedInterfaces();
            content += "<p>builder.RegisterAssemblyTypes(typeof(AutoFac).Assembly).Where(t => t.Name.EndsWith(\"Repository\")).AsImplementedInterfaces();</p>";

            content += "<h2>Registering modules</h2>";
            // Registering modules
            builder.RegisterModule(new MyModule());
            content += "<p>builder.RegisterModule(new MyModule());</p>";

            content += "<h2>Building the container</h2>";
            // Building the container
            var container = builder.Build();
            content += "<p>var container = builder.Build();</p>";

            content += "<h2>Resolving dependencies</h2>";
            // Resolving dependencies
            using (var scope = container.BeginLifetimeScope())
            {
                var service = scope.Resolve<IMyService>();
                service.DoSomething();
            }
            content += "<p>var service = scope.Resolve<IMyService();</p>";

            // Create a PDF from the HTML string using C#
            var pdf = renderer.RenderHtmlAsPdf(content);
            // Export to a file or Stream
            pdf.SaveAs("autofac.pdf");
            Console.WriteLine("We are done...");
            Console.ReadKey();
        }
    }

    internal interface IMyService
    {
        void DoSomething();
    }

    internal class MyModule : Module
    {
        protected override void Load(ContainerBuilder builder)
        {
            // Register module dependencies here
        }
    }

    internal class MyService : IMyService
    {
        public void DoSomething()
        {
            Console.WriteLine("DoSomething");
        }
    }
}
using Autofac;
using CacheManager.Core;
using IronPdf;
using System.Reflection;

namespace IronPdfDemos
{
    public class AutoFac
    {
        public static void Execute()
        {
            // Instantiate Cache and ChromePdfRenderer
            var renderer = new ChromePdfRenderer();
            var cache = CacheFactory.Build("ironPdfAutofac", settings =>
            {
                settings.WithDictionaryHandle();
            });

            // Prepare HTML content
            var content = "<h1>Demonstrate Autofac with IronPDF</h1>";
            content += "<p>This is an illustration of using Autofac for dependency injection and IronPDF for generating PDF documents.</p>";
            content += "<h2>Setting up Autofac container</h2>";

            // Setting up Autofac container
            var builder = new ContainerBuilder();
            content += "<p>var builder = new ContainerBuilder();</p>";

            content += "<h2>Registering types manually</h2>";
            // Registering types manually
            builder.RegisterType<MyService>().As<IMyService>();
            content += "<p>builder.RegisterType<MyService>().As<IMyService();</p>";

            content += "<h2>Registering types using assembly scanning</h2>";
            // Registering types using assembly scanning
            builder.RegisterAssemblyTypes(typeof(AutoFac).Assembly)
                .Where(t => t.Name.EndsWith("Repository"))
                .AsImplementedInterfaces();
            content += "<p>builder.RegisterAssemblyTypes(typeof(AutoFac).Assembly).Where(t => t.Name.EndsWith(\"Repository\")).AsImplementedInterfaces();</p>";

            content += "<h2>Registering modules</h2>";
            // Registering modules
            builder.RegisterModule(new MyModule());
            content += "<p>builder.RegisterModule(new MyModule());</p>";

            content += "<h2>Building the container</h2>";
            // Building the container
            var container = builder.Build();
            content += "<p>var container = builder.Build();</p>";

            content += "<h2>Resolving dependencies</h2>";
            // Resolving dependencies
            using (var scope = container.BeginLifetimeScope())
            {
                var service = scope.Resolve<IMyService>();
                service.DoSomething();
            }
            content += "<p>var service = scope.Resolve<IMyService();</p>";

            // Create a PDF from the HTML string using C#
            var pdf = renderer.RenderHtmlAsPdf(content);
            // Export to a file or Stream
            pdf.SaveAs("autofac.pdf");
            Console.WriteLine("We are done...");
            Console.ReadKey();
        }
    }

    internal interface IMyService
    {
        void DoSomething();
    }

    internal class MyModule : Module
    {
        protected override void Load(ContainerBuilder builder)
        {
            // Register module dependencies here
        }
    }

    internal class MyService : IMyService
    {
        public void DoSomething()
        {
            Console.WriteLine("DoSomething");
        }
    }
}
Imports Autofac
Imports CacheManager.Core
Imports IronPdf
Imports System.Reflection

Namespace IronPdfDemos
	Public Class AutoFac
		Public Shared Sub Execute()
			' Instantiate Cache and ChromePdfRenderer
			Dim renderer = New ChromePdfRenderer()
			Dim cache = CacheFactory.Build("ironPdfAutofac", Sub(settings)
				settings.WithDictionaryHandle()
			End Sub)

			' Prepare HTML content
			Dim content = "<h1>Demonstrate Autofac with IronPDF</h1>"
			content &= "<p>This is an illustration of using Autofac for dependency injection and IronPDF for generating PDF documents.</p>"
			content &= "<h2>Setting up Autofac container</h2>"

			' Setting up Autofac container
			Dim builder = New ContainerBuilder()
			content &= "<p>var builder = new ContainerBuilder();</p>"

			content &= "<h2>Registering types manually</h2>"
			' Registering types manually
			builder.RegisterType(Of MyService)().As(Of IMyService)()
			content &= "<p>builder.RegisterType<MyService>().As<IMyService();</p>"

			content &= "<h2>Registering types using assembly scanning</h2>"
			' Registering types using assembly scanning
			builder.RegisterAssemblyTypes(GetType(AutoFac).Assembly).Where(Function(t) t.Name.EndsWith("Repository")).AsImplementedInterfaces()
			content &= "<p>builder.RegisterAssemblyTypes(typeof(AutoFac).Assembly).Where(t => t.Name.EndsWith(""Repository"")).AsImplementedInterfaces();</p>"

			content &= "<h2>Registering modules</h2>"
			' Registering modules
			builder.RegisterModule(New MyModule())
			content &= "<p>builder.RegisterModule(new MyModule());</p>"

			content &= "<h2>Building the container</h2>"
			' Building the container
			Dim container = builder.Build()
			content &= "<p>var container = builder.Build();</p>"

			content &= "<h2>Resolving dependencies</h2>"
			' Resolving dependencies
			Using scope = container.BeginLifetimeScope()
				Dim service = scope.Resolve(Of IMyService)()
				service.DoSomething()
			End Using
			content &= "<p>var service = scope.Resolve<IMyService();</p>"

			' Create a PDF from the HTML string using C#
			Dim pdf = renderer.RenderHtmlAsPdf(content)
			' Export to a file or Stream
			pdf.SaveAs("autofac.pdf")
			Console.WriteLine("We are done...")
			Console.ReadKey()
		End Sub
	End Class

	Friend Interface IMyService
		Sub DoSomething()
	End Interface

	Friend Class MyModule
		Inherits Module

		Protected Overrides Sub Load(ByVal builder As ContainerBuilder)
			' Register module dependencies here
		End Sub
	End Class

	Friend Class MyService
		Implements IMyService

		Public Sub DoSomething() Implements IMyService.DoSomething
			Console.WriteLine("DoSomething")
		End Sub
	End Class
End Namespace
VB   C#

Code Explanation

Let’s break down the code snippet you provided:

  1. ChromePdfRenderer Setup:

    • The code initializes a ChromePdfRenderer instance for rendering PDFs.
  2. HTML Content Preparation:

    • The content variable is an HTML string that will be used to generate the PDF.
    • It includes an <h1> tag with the title "Demonstrate Autofac with IronPDF".
  3. Setting Up Autofac Container:

    • The code creates an instance of ContainerBuilder named builder.
    • This is the first step in setting up an Autofac container for dependency injection.
  4. Registering Types Manually:

    • It registers a type MyService as an implementation of the IMyService interface.
    • This allows Autofac to resolve dependencies when needed.
  5. Registering Types Using Assembly Scanning:

    • It scans the assembly containing the AutoFac type.
    • Registers types whose names end with "Repository" as implementations of their corresponding interfaces.
  6. Registering Modules:

    • It registers a module called MyModule.
    • Modules allow the grouping of related registrations.
  7. Building the Container:

    • The container is built from the registered components using the builder.Build() method.
  8. Resolving Dependencies:

    • Inside a lifetime scope (using (var scope = container.BeginLifetimeScope())), it resolves an instance of IMyService.
    • The DoSomething method is called on the resolved service.
  9. PDF Generation:
    • A PDF is created from the content using the ChromePdfRenderer.
    • The resulting PDF is saved as "autofac.pdf".

Output

Autofac .NET 6 (How It Works For Developers): Figure 6 - Outputted PDF from the previous code example

IronPDF License

IronPDF requires a license key. Place the license key in the appSettings.json file as shown below.

{
  "IronPdf.License.LicenseKey": "The Key Here"
}

Conclusion

In conclusion, Autofac.NET stands as a robust and feature-rich dependency injection container for .NET, empowering developers to build modular, maintainable, and extensible applications. Whether you're developing desktop applications, web services, or cloud-native solutions, Autofac offers a reliable foundation for managing dependencies and promoting best practices in .NET development.

IronPDF is a versatile and feature-rich library to generate, edit, and read PDF documents. Together with the IronPDF library from Iron Software to read and generate PDF documents, developers can gain advanced skills to develop modern applications.

< PREVIOUS
OpenTelemetry .NET (How It Works For Developers)
NEXT >
Papercut SMTP C# (How It Works For Developers)

Ready to get started? Version: 2024.10 just released

Free NuGet Download Total downloads: 10,912,787 View Licenses >