注入实现接口的控制器

时间:2019-06-14 09:26:36

标签: c# asp.net-mvc asp.net-core dependency-injection

在ASP.NET Core MVC中,将自动解析实现Controller的所有类并将其添加到MVC管道中。也可以使用services.AddMvc().AddControllersAsServices();

将这些控制器注入DI容器中

我还有一个控制器,该控制器还实现了特定的接口,也可以将其添加到DI容器中:services.AddSingleton<IMyInterface, MyImpl>();

public class MyImpl : Controller, IMyInterface { }

但是,如果此控制器也实现了Controller,它已经被添加到AddControllersAsServices()中,那么再将其添加到DI容器一次,将导致该类有两个实例。

进行此设计的原因是,我将有IMyInterface的多个实现,后来需要决定使用哪个实现,但是每个实现也都需要成为一个控制器,以提供某些API端点(每个控制器将提供不同的端点,因此不会有任何冲突。

如何确保仅实例化类的一个实例,然后如何获得IMyInterface的所有实现?

2 个答案:

答案 0 :(得分:1)

在每次请求时都会实例化控制器类,因此即使您指定了类似这样的内容(Ninject样式):

services.Bind<IMyInterface, MyController>().To<MyController>().InSingletonScope();

这将非常糟糕。我的意思是,Controller处于有状态状态,您只需混合所有内容并破坏其内部上下文。 您可能要做的是通过控制器进行装饰,而不是自己管理其寿命:

public class MyImpl : IMyInterface
{
}

public class MyController : Controller
{
     private readonly IMyInterface _inner; //delegate implementation to this one.
     public MyController(IMyInterface inner)
     {
         _inner = inner;
     }
}

然后注射:

services.Bind<IMyInterface>().To<MyImpl>().InSingletonScope();//this is your logic.
sercices.Bind<MyController>().ToSomethingWhatever();//this line is managed by ASP .NET, mentioned this only to show the idea

答案 1 :(得分:0)

您可能需要删除从Controller类继承的MyImpl。另外,您还需要将MyImpl视为服务而不是Controller。

另一个选择是,这可以使用IoC容器(例如Autofac或Ninject或Castle Windsor)来实现。当与Autofac一起使用时,将类似于以下内容

  1. 使用NuGet软件包添加Autofac,Autofac ASP.Net MVC4集成
  2. 打开GLobal.asax.cs
  3. 在Application_Start()中进行以下更改。 3a。将以下代码注释为

    // WebApiConfig.Register(GlobalConfiguration.Configuration);

3b。创建一个新方法RegisterAutofac(),将其作为Application_Start()中的第一个方法调用 3c。下面是RegisterAutofac()方法的示例实现

private void RegisterAutofac()
{
    var builder = new Autofac.ContainerBuilder();
    builder.RegisterControllers(Assembly.GetExecutingAssembly());
    builder.RegisterSource(new ViewRegistrationSource());

    // The object to be injected in constructor etc.
    builder.RegisterType<MyImpl>().As<IMyInterface>().SingleInstance();
    var container = builder.Build();
    DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
}