Autofac 和 MVC 集成:每个 API 控制器的寄存器类型

本文关键字:控制器 寄存器 类型 API 每个 MVC 集成 Autofac | 更新日期: 2023-09-27 18:34:54

我正在使用.Net 4.5,ASP.NET MVC 5和NuGet包:自动 3.5.2Autofac ASP.NET Web API 5 Integration 3.0.0-rc1

我有一个接口的 2 种不同的实现:

public class MemoryStreamService : IStreamService { ... }
public class HttpStreamService : IStreamService { ... }

还有另一个通过构造函数注入使用接口的具体类:

public class MainService : IMainService 
{
    public MainService(IStreamService streamService) { ... }
}

我有 2 个 ASP.NET Web API 控制器,通过构造函数注入使用主服务:

public class MemoryStreamController : ApiController 
{
    public MemoryStreamController(IMainService mainService) { ... }
}
public class HttpStreamController : ApiController 
{
    public HttpStreamController(IMainService mainService) { ... }
}

我想要的是当IStreamService的实例需要在调用MemoryStreamController的上下文中实例化时使用MemoryStreamService实现,当我们在调用HttpStreamController的上下文中时,使用HttpStreamService实现。

我试图通过在 Global.asax 的 Application_Start(( 的 Autofac 生成器中注册控制器和服务类来实现这一点.cs

方式如下:
builder.RegisterType<MainService>().As<IMainService>();
builder.RegisterType<MemoryStreamService>()
       .As<IStreamService>()
       .InstancePerApiControllerType(typeof(MemoryStreamController));
builder.RegisterType<HttpStreamService>()
       .As<IStreamService>()
       .InstancePerApiControllerType(typeof(HttpStreamController));
builder.RegisterApiControllers(Assembly.GetExecutingAssembly());

但看起来 InstancePerApiControllerType(( 不适用于此:对于两个控制器,我总是获得 IStreamService 的第一个注册实现类型(在本示例中为 MemoryStreamController(。

我需要如何配置 Autofac 以便在 MemoryStreamController 处理的请求上下文中获取 MemoryStreamService 实例,以及为 HttpStreamController 发起的调用配置 HttpStreamService 实例?

编辑:如果我没有对控制器使用依赖注入,我会这样做:

public class MemoryStreamController : ApiController 
{
    public MemoryStreamController() 
    {
        this.mainService = new MainService(new MemoryStreamService());
    }
}
public class HttpStreamController : ApiController 
{
    public HttpStreamController()
    {
        this.mainService = new MainService(new HttpStreamService());
    }
}

所以我的问题可以理解为:如何使用 Autofac 注册我的控制器和所有服务来实现相同的目标?

Autofac 和 MVC 集成:每个 API 控制器的寄存器类型

这个

怎么样。首先,将服务注册为:

builder.RegisterType<MemoryStreamService>()
   .Named<IStreamService>("MemoryStreamService")
   .InstancePerApiControllerType(typeof(MemoryStreamController));
builder.RegisterType<HttpStreamService>()
   .Named<IStreamService>("HttpStreamService")
   .InstancePerApiControllerType(typeof(HttpStreamController));

然后注册一个 func 工厂,该工厂可以根据名称解析正确的服务。喜欢这个:

builder.Register<Func<string, IStreamService>>(c =>
        {
            var context = c.Resolve<IComponentContext>();
            return service =>
            {
                return context.ResolveNamed<IStreamService>(service);
            };
        });

然后在控制器中解析IMainService时,可以注入Func<string, IMainService>(MainService构造函数中的第一个参数必须是字符串(。这样,您可以传递要解析的服务的名称。喜欢这个:

public class MemoryStreamController : ApiController 
{
    private IMainService _service;
    public MemoryStreamController(Func<string, IMainService> mainService) 
    {
        _service = mainService("MemoryStreamService")
    }
}

然后在 MainService 的构造函数中,使用注入的类型名称调用 func 工厂。喜欢这个:

public MainService(string type, Func<string, IStreamService> factory)
{
    _service = factory(type);
} 

我遵循了@TravisIllig建议(谢谢!(并且:
1( 对两个"流服务"都使用命名注册,
2( 为 MainService 使用了 2 个命名注册,它们在可以作为参数
的流服务类型上有所不同3( 通过根据需要指定每个命名的主服务来注册控制器。

builder.RegisterType<MemoryStreamService>().Named<IStreamService>("memoryService");
builder.RegisterType<HttpStreamService>().Named<IStreamService>("httpService");
builder
    .RegisterType<MainService>()
    .As<IMainService>()
    .WithParameter(ResolvedParameter.ForNamed<IStreamService>("memoryService"))
    .Named<IMainService>("mainServiceForMemoryStreams");
builder
    .RegisterType<MainService>()
    .As<IMainService>()
    .WithParameter(ResolvedParameter.ForNamed<IStreamService>("httpService"))
    .Named<IMainService>("mainServiceForHttpStreams");
// This is for registering the other controllers of my API
builder.RegisterApiControllers(Assembly.GetExecutingAssembly());
// Manually registers controllers that need an specific instance of IStreamService.
// These registrations needs to be placed after the "RegisterApiControllers()" call in order to Autofac to perform the desired injections.
builder.RegisterType<MemoryStreamController>()
       .WithParameter(ResolvedParameter.ForNamed<IMainService>("mainServiceForMemoryStreams"));
builder.RegisterType<HttpStreamController>()
       .WithParameter(ResolvedParameter.ForNamed<IMainService>("mainServiceForHttpStreams"));