在ASP.NET Core MVC中,将自动解析实现Controller
的所有类并将其添加到MVC管道中。也可以使用services.AddMvc().AddControllersAsServices();
我还有一个控制器,该控制器还实现了特定的接口,也可以将其添加到DI容器中:services.AddSingleton<IMyInterface, MyImpl>();
public class MyImpl : Controller, IMyInterface { }
但是,如果此控制器也实现了Controller
,它已经被添加到AddControllersAsServices()
中,那么再将其添加到DI容器一次,将导致该类有两个实例。
进行此设计的原因是,我将有IMyInterface
的多个实现,后来需要决定使用哪个实现,但是每个实现也都需要成为一个控制器,以提供某些API端点(每个控制器将提供不同的端点,因此不会有任何冲突。
如何确保仅实例化类的一个实例,然后如何获得IMyInterface
的所有实现?
答案 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一起使用时,将类似于以下内容
在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));
}