patterncsharpMajor
Autofac DI container in console app
Viewed 0 times
consoleautofaccontainerapp
Problem
Just used DI containers in MVC projects, via constructor injection, and I'd need to now inject a service into a console app. I'm using Autofac so I followed what I found here.
The code would be something like this:
The service the console app depends on:
The console app main method
It's using the Service Locator if I'm not wrong (I'm trying to get my head around all of this), which I would be likely to avoid in case I could as it's thoroughly discussed in the web. But can I actually avoid it in a console app? Can any see any big flaw with this implementation?
The main method is almost as simple as this one, only one call to one service (although the service doesn't write a console). And that's the only code in the project in fact.
The code would be something like this:
The service the console app depends on:
public interface IBatchService
{
void WriteInformation(string input);
}
public class BatchService : IBatchService
{
public void WriteInformation(string input)
{
Console.WriteLine(input);
Console.ReadKey();
}
}The console app main method
public class Program
{
private static IContainer Container { get; set; }
static void Main(string[] args)
{
var builder = new ContainerBuilder();
builder.RegisterType().As();
Container = builder.Build();
using (var scope = Container.BeginLifetimeScope())
{
var batchService = scope.Resolve();
batchService.WriteInformation("Injected!");
}
}It's using the Service Locator if I'm not wrong (I'm trying to get my head around all of this), which I would be likely to avoid in case I could as it's thoroughly discussed in the web. But can I actually avoid it in a console app? Can any see any big flaw with this implementation?
The main method is almost as simple as this one, only one call to one service (although the service doesn't write a console). And that's the only code in the project in fact.
Solution
Your
There's not enough meat in this project to even justify using DI/IoC: you have a service that nothing depends on.
If you had, say, an
...then composition would refer to resolving all dependencies of an
The
You don't need the static
I'd make it something like this:
Then your
Actually, this:
I'd move elsewhere; as your application grows, you'll be registering tons of stuff here, registration is a concern of its own, that deserves its own class IMO. That class can be
The configuration class could look like this:
Leaving your
Main method has too many responsibilities: it's your application's composition root, and it's executing the program's logic... if printing to Console can be considered logic.There's not enough meat in this project to even justify using DI/IoC: you have a service that nothing depends on.
If you had, say, an
Application class:public interface IApplication
{
void Run();
}
public class Application : IApplication
{
private readonly IBatchService _service;
public Application(IBatchService service)
{
_service = service;
}
public void Run()
{
_service.WriteInformation("Injected!");
}
}...then composition would refer to resolving all dependencies of an
Application instance, regardless of how complex that might be.The
Main method would only ask for an Application instance (let's call it app), and your IoC container would do its job - the Main method would only call app.Run();, and the rest of the application doesn't need to know there's an IoC container involved.You don't need the static
IContainer field; I've never used Autofac (you should look into Ninject, seems much simpler), but your IoC container should only live (and die) in the Main method - if you're using it anywhere else, you're doing something wrong (Service Locator).I'd make it something like this:
static void Main(string[] args)
{
var builder = new ContainerBuilder();
builder.RegisterType().As();
var container = builder.Build();
using (var scope = container.BeginLifetimeScope())
{
var app = scope.Resolve();
app.Run();
}
}Then your
Main method is done with. If you're going to expand the application, you just inject new dependencies, and consume them.Actually, this:
builder.RegisterType().As();I'd move elsewhere; as your application grows, you'll be registering tons of stuff here, registration is a concern of its own, that deserves its own class IMO. That class can be
static for all you care, it's infrastructure stuff, its only goal is to spit out a configured IContainer.The configuration class could look like this:
public static class ContainerConfig
{
public static IContainer Configure()
{
var builder = new ContainerBuilder();
builder.RegisterType().As();
// add other registrations here...
return builder.Build();
}
}Leaving your
Main method like this:static void Main(string[] args)
{
var container = ContainerConfig.Configure();
using (var scope = container.BeginLifetimeScope())
{
var app = scope.Resolve();
app.Run();
}
}Code Snippets
public interface IApplication
{
void Run();
}
public class Application : IApplication
{
private readonly IBatchService _service;
public Application(IBatchService service)
{
_service = service;
}
public void Run()
{
_service.WriteInformation("Injected!");
}
}static void Main(string[] args)
{
var builder = new ContainerBuilder();
builder.RegisterType<BatchService.BatchService>().As<IBatchService>();
var container = builder.Build();
using (var scope = container.BeginLifetimeScope())
{
var app = scope.Resolve<IApplication>();
app.Run();
}
}builder.RegisterType<BatchService.BatchService>().As<IBatchService>();public static class ContainerConfig
{
public static IContainer Configure()
{
var builder = new ContainerBuilder();
builder.RegisterType<BatchService.BatchService>().As<IBatchService>();
// add other registrations here...
return builder.Build();
}
}static void Main(string[] args)
{
var container = ContainerConfig.Configure();
using (var scope = container.BeginLifetimeScope())
{
var app = scope.Resolve<IApplication>();
app.Run();
}
}Context
StackExchange Code Review Q#56197, answer score: 32
Revisions (0)
No revisions yet.