Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use Autofac in a class library project?

I have the following implementation:

private INewsRepository newsRepository;

public NewsService(INewsRepository newsRepository)
{
     this.newsRepository = newsRepository;
}

This service is in a separate project than that of my web project. Where and how would I specify the dependency injection? Would I still need to put it in my global.asax file? What if this service is used my other apps as well?

like image 855
Brendan Vogt Avatar asked Feb 01 '11 12:02

Brendan Vogt


People also ask

What is Autofac library?

¶ Autofac is an addictive IoC container for . NET. It manages the dependencies between classes so that applications stay easy to change as they grow in size and complexity. This is achieved by treating regular .

Why do we need Autofac?

AutoFac provides better integration for the ASP.NET MVC framework and is developed using Google code. AutoFac manages the dependencies of classes so that the application may be easy to change when it is scaled up in size and complexity.


3 Answers

You should only reference the container from the root of the application (global.asax). This is known as the Register Resolve Release pattern.

Your correct use of Constructor Injection ensures that you can reuse the NewsService class from other applications without requiring that those other applications use a particular DI Container (or any at all).

This is a good start at designing the service in a DI Friendly manner, yet keeping it container agnostic.

like image 71
Mark Seemann Avatar answered Sep 18 '22 17:09

Mark Seemann


[TestClass]
public class LogTest 
{
    /// <summary>
    /// Test project: autofac impl.
    /// </summary>
    private readonly ContainerBuilder _builder; 
    private readonly IContainer _container;

    /// <summary>
    /// Initializes a new instance of the <see cref="LogTest" /> class.
    /// </summary>
    public LogTest()
    {
        //
        // Read autofac setup from the project we are testing
        //
        _builder = new ContainerBuilder();
        Register.RegisterTypes(_builder);
        _container = _builder.Build();

        loggingService = _container.Resolve<ILoggingService>(new NamedParameter("theType", this));
    }

    [TestMethod]
    public void DebugMsgNoExectption()
    {
        var a = _container.Resolve<IHurraService>();
        var b = a.ItsMyBirthday();

public class HurraService : IHurraService
{
    private IHurraClass _hurra;

    /// <summary>
    /// Initializes a new instance of the <see cref="HurraService" /> class.
    /// </summary>
    public HurraService(IHurraClass hurra)
    {
        _hurra = hurra;
    }

    /// <summary>
    /// It my birthday.
    /// </summary>
    public string ItsMyBirthday()
    {
        return _hurra.Hurra();
    }
}

public static class Register
{
    public static void RegisterTypes(ContainerBuilder builder)
    {
        builder.RegisterType<LoggingService>().As<ILoggingService>();
        builder.RegisterType<HurraService>().As<IHurraService>();
        builder.RegisterType<HurraClass>().As<IHurraClass>();
    }
}

Inside the Class Library I created the "Register" class. Here the Autofac setup is done. In my test project I read this file (Register.RegisterTypes) and init the _container.

Now I have access to Resolve all the goodies inside the project I am testing.

like image 37
Hessner Avatar answered Sep 20 '22 17:09

Hessner


I guess it would depend on whether you intend to use the same assembly in multiple host applications. Does the assembly really require references to AutoFac? I would recommend against this, as if your requirements change later you would have a load of unnecessary references. Your host application should control how to assemble the modular parts, so I would leave configuration up to your host (in this case your web application. If you want to push some control of registration, you could create a type which handles the registration for you, but as I mentioned before, your assembly is essentially bound to using AutoFac e.g.:

public static class NewsRegistration()
{
    public static void RegisterTypes(ContainerBuilder builder)
    {
        // Register your specific types here.
        builder.RegisterType<NewsService>().As<INewsService>();
    }
}

That way you could easily call:

var builder = new ContainerBuilder();
// Register common types here?

NewsRegistration.RegisterTypes(builder);

var container = builder.Build();
like image 25
Matthew Abbott Avatar answered Sep 20 '22 17:09

Matthew Abbott