I don't hide it -- Autofac in C# is my favorite dependency injection framework. I wanted to put together this quick article for you on a handful of tips for getting started with Autofac, especially if you're a beginner to dependency injection!
Autofac is a flexible dependency injection container for .NET applications, allowing you to efficiently manage and resolve dependencies between classes. This helps with making your code more modular, maintainable, and testable. I'll go over 3 simple tips to get you up and running with Autofac in C# as your dependency injection framework!
What's In This Article: Autofac in C#
Remember to check out these platforms:
// FIXME: social media icons coming back soon!
Tip 1: Installing Autofac in C#
To use Autofac in C# for dependency injection, you'll need to install the Autofac NuGet package. One of the drawbacks of Autofac as a dependency injection framework is that it is an external package, and others may just want to rely on the built-in IServiceCollection dependency framework we get with things like ASP.NET Core.
To install Autofac in your C# project, follow these steps:
- Open your project in Visual Studio.
- Right-click on the "References" node in the Solution Explorer window.
- Select "Manage NuGet Packages" from the context menu.
- In the NuGet Package Manager window, search for "Autofac" using the search bar.
- Once you find the "Autofac" package, click on it to select it.
- Click on the "Install" button to begin the installation process.
- Review the package details and click "OK" to confirm the installation.
- Visual Studio will now download and install the Autofac package and all its dependencies.
By using a package manager like NuGet for installation, you ensure that the correct version of Autofac is installed along with any necessary dependencies. This eliminates the need for manually downloading and managing individual DLL files. After the installation is complete, you are ready to start using Autofac in your C# project for dependency injection. We'll see in the upcoming sections how to configure the container for resolving dependencies, and some different flavors of how things can be resolved!
Tip 2: Autofac Container Configuration
Configuration of the dependency container in Autofac allows us to register dependencies and set up the environment for dependency injection to work. To start, let's talk about why this configuration is important when using Autofac. Configuration is all about how the dependency injection framework should behave within our application.
We can specify which classes to register, how dependencies should be resolved, and how instances should be created. By properly configuring the Autofac container, we ensure that the correct dependencies are injected into our objects, promoting modularity and testability in our codebase. In a later tip, we'll see how we can resolve dependencies in different ways.
To configure the Autofac container in a C# application, follow these steps (assuming you already followed tip 1 to get Autofac installed):
Create Your Class or Method For Configuration
Personally, I like organizing my registration code into Autofac modules. However, there's nothing that says we have to! So we can look at just creating a class here that will house our registration logic. We can make a static class called AutofacConfig
.
Inside the AutofacConfig
class, we create a static method, let's name it ConfigureContainer
, which takes an IContainerBuilder
parameter. This method will handle the registration of dependencies inside the Autofac container. This is shaping up to be very much like a "Module", but I wanted to show you that you're not forced into that if you don't want to be.
Here's an example:
public static void ConfigureContainer(ContainerBuilder builder)
{
// Register dependencies here
builder.RegisterType<MyDependency>().As<IMyDependency>();
builder.RegisterType<MyService>().As<IMyService>();
}
In the code snippet above, we register two dependencies: MyDependency
and MyService
. The As
method indicates the interfaces they implement, IMyDependency
and IMyService
, respectively. We have a lot of different flexibility we can look at here, ranging from how you resolve the types to singleton behavior of these types. The configuration can get very complex, but Autofac has many powerful features that you can leverage to register things as you need.
Container From ContainerBuilder in Autofac
In the Main
method or the entry point of our application, we need to instantiate the Autofac container and call the ConfigureContainer
method to configure it. Here's an example:
static void Main(string[] args)
{
var builder = new ContainerBuilder();
AutofacConfig.ConfigureContainer(builder);
var container = builder.Build();
// Continue with the application logic
}
In the code snippet above, we create an instance of the ContainerBuilder
class, call the ConfigureContainer
method from the AutofacConfig
class, and then build the container using the Build
method. After that, the container is ready to resolve and inject dependencies throughout the application.
As to avoid the anti-pattern called "The Service Locator Pattern", it's generally recommended to resolve something like the main dependency out of your container to kick off the rest of your application. Otherwise, we might find ourselves in a position where we're passing the container around to different places and trying to resolve dependencies out of it. In reality, those other things resolving dependencies off the container manually should probably just be classes wired up to the container to do auto-resolution.
Tip 3: Resolving Dependencies in Autofac
In software engineering, dependency resolution refers to the process of providing an instance of a class or interface to another class that depends on it. In Autofac, resolving dependencies is made easy through its container-based dependency injection system.
When it comes to resolving dependencies using Autofac, there are a few different approaches you can take. Let's explore some of them:
Constructor Injection in Autofac
This is the most common approach to injecting dependencies in Autofac. With constructor injection, dependencies are passed to a class through its constructor. This allows for easy testing and makes dependencies explicit. You get the most "magic" out of this approach because the resolution can happen for you automatically with very little effort. This is my go-to way of wiring up my dependencies in 99.9% of what I do.
Here's an example:
public class UserService : IUserService
{
private readonly IUserRepository _userRepository;
public UserService(IUserRepository userRepository)
{
_userRepository = userRepository;
}
// Class implementation...
}
// our registration code
builder
.RegisterType<UserRepository>()
.AsImplementedInterfaces()
.SingleInstance();
builder
.RegisterType<UserService>()
.AsImplementedInterfaces()
.SingleInstance();
In the above example, the UserService
class depends on the IUserRepository
. The dependency is provided through the constructor, and Autofac takes care of resolving and injecting the IUserRepository
instance.
Method Injection in Autofac
Another option in Autofac is method injection, where dependencies are provided through specific methods. This can be useful when you need to inject dependencies dynamically or at specific times.
Here's an example:
public class Logger
{
public void Log(string message)
{
// Logging implementation...
}
}
public class Worker
{
private Logger _logger;
public void SetLogger(Logger logger)
{
_logger = logger;
}
// Other class implementation...
}
// in our registration code:
builder.Register(c => {
var worker = new Worker();
var logger = c.Resolve<Logger>();
worker.SetLogger(logger);
return result;
});
In the above example, the Worker
class has a method called SetLogger
which accepts a Logger
instance. Autofac allows you to configure this injection, but it takes a little bit more manual effort than if we used constructors.
Property Injection in Autofac
In some cases, you may want to inject dependencies through properties rather than constructors. Like method injection, we can manually set the property inside of our registration hook up on the container.
Here's an example:
public class Logger
{
public void Log(string message)
{
// Logging implementation...
}
}
public class Worker
{
public Logger { get; set;}
// Other class implementation...
}
// in our registration code:
builder.Register(c => {
var worker = new Worker();
var logger = c.Resolve<Logger>();
worker.Logger = logger;
return result;
});
While this example is nearly identical to method injection, property injection can get significantly more complicated with Autofac. Truthfully, it's not something I've ever had to use and while I wouldn't say I actively design to "avoid it" -- I have certainly never designed anything that needed it. I'd highly recommend heading over to the official Autofac docs on this one for further reading!
By leveraging these different approaches to dependency resolution, you can effectively organize and manage dependencies in your C# projects with Autofac. Remember, in all cases, you'll need to configure the Autofac container with the appropriate dependencies during setup. This is typically done in the application's composition root.
Wrapping Up Autofac in C#
Understanding dependency injection in C# and utilizing Autofac can significantly improve your code quality and development experience. However, there is always more to learn and explore -- like checking out Scrutor for dependency injection instead! As much as I like Autofac, I am making a point to investigate other options so I can learn about what's available. I encourage you to do the same :)
If you found this useful and you're looking for more learning opportunities, consider subscribing to my free weekly software engineering newsletter and check out my free videos on YouTube!
Affiliations
These are products & services that I trust, use, and love. I get a kickback if you decide to use my links. There’s no pressure, but I only promote things that I like to use!
- BrandGhost: My social media content and scheduling tool that I use for ALL of my content!
- RackNerd: Cheap VPS hosting options that I love for low-resource usage!
- Contabo: Affordable VPS hosting options!
- ConvertKit: The platform I use for my newsletter!
- SparkLoop: Helps add value to my newsletter!
- Opus Clip: Tool for creating short-form videos!
- Newegg: For all sorts of computer components!
- Bulk Supplements: Huge selection of health supplements!
- Quora: I answer questions when folks request them!