Ricky Yip
Ricky Yip

Reputation: 303

Get different interface in two controllers with Autofac

I want to use different interface in different controller.

public interface IMessenger {
    Id {get; set;}
    void Send();
}

I have two class implement two same interface.

public class SmsSender : IMessenger {
    public Id {get; set;}
    public void Send() {
         //logic here
    }    
}

public class MailSender : IMessenger {
    public Id {get; set;}
    public void Send() {
         //logic here
    }    
}

Two Controllers:

public class HomeController : Controller {

    private readonly IMessenger _messenger;

    public HomeController(IMessenger messenger) {
        _messenger = messenger;
    }
}


public class Home2Controller : Controller {

    private readonly IMessenger _messenger;

    public HomeController(IMessenger messenger) {
        _messenger = messenger;
    }
}

Autofaq setup:

builder.RegisterType<MailSender>().As<IMessenger>().InstancePerLifetimeScope();

builder.RegisterType<SmsSender>().As<IMessenger>().InstancePerLifetimeScope();

How can I get SmsSender in HomeController and MailSender in Home2Controller?

Upvotes: 2

Views: 305

Answers (2)

Cyril Durand
Cyril Durand

Reputation: 16192

When you register your component you can tell Autofac which dependency to choose using the WithParameter method.

builder.RegisterType<Service>()
       .As<IService>()
       .WithParameter((pi, c) => pi.ParameterType == typeof(IDependency),
                      (pi, c) => new XDependency());

In order to avoid the new XDependency code and let Autofac create the dependency, you can resolve a named registration.

builder.RegisterType<XDependency>().Named<IDependency>("X");
builder.RegisterType<YDependency>().Named<IDependency>("Y");

and resolve it using c.ResolveNamed<IDependency>("X")

Another solution would be to let the component choose which dependency it wants using IIndex<TKey, TService>. To use this, you have to register your IDependency as named registrations and inject IIndex<String, IDependency>.

public class Service 
{
    public Service(IIndex<String, IDependency> dependencies)
    {
        this._dependency = dependencies["X"]; 
    }

    private readonly IDependency _dependency;
}

For more information you can have a look at the FAQ on the autofac documentation : How do I pick a service implementation by context

Upvotes: 4

Stephen Zeng
Stephen Zeng

Reputation: 2818

You cannot. Autofac won't be able to figure out the differences. Better to separate them into two different interfaces, inject the one you need into controllers. From the design point of view the dependency is clearer as well. If there is a need, both interfaces can implement IMessenger.

Upvotes: 0

Related Questions