使用 Autofac 在两个控制器中获得不同的接口

本文关键字:接口 控制器 两个 Autofac 使用 | 更新日期: 2023-09-27 17:55:42

我想在不同的控制器中使用不同的接口。

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

我有两个类实现两个相同的接口。

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
    }    
}

两个控制器:

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;
    }
}

自动常见问题解答设置:

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

如何在HomeController中获取SmsSender,在Home2Controller中获取MailSender

使用 Autofac 在两个控制器中获得不同的接口

注册组件时,可以使用 WithParameter 方法告诉 Autofac 选择哪个依赖项。

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

为了避免new XDependency代码并让 Autofac 创建依赖项,您可以解析命名注册。

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

并使用c.ResolveNamed<IDependency>("X")解决它

另一种解决方案是让组件使用 IIndex<TKey, TService> 选择它想要的依赖项。要使用它,您必须将IDependency注册为命名注册并注入IIndex<String, IDependency>

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

有关更多信息,您可以查看 autofac 文档中的常见问题解答:如何按上下文选择服务实现

你不能。Autofac将无法找出差异。最好将它们分成两个不同的接口,将您需要的接口注入控制器。从设计的角度来看,依赖关系也更清晰。如果需要,两个接口都可以实现 IMessenger。