Контроллеры Inject, которые реализуют интерфейс - PullRequest
1 голос
/ 14 июня 2019

В ASP.NET Core MVC все классы, которые реализуют Controller, будут автоматически разрешены и добавлены в конвейер MVC.Эти контроллеры также могут быть введены в контейнер DI с помощью services.AddMvc().AddControllersAsServices();

У меня также есть контроллер, который также реализует специальный интерфейс, который я также могу добавить в контейнер DI: services.AddSingleton<IMyInterface, MyImpl>();

public class MyImpl : Controller, IMyInterface { }

Тем не менее, поскольку этот контроллер также реализует Controller, он уже был добавлен в AddControllersAsServices(), поэтому добавление его в контейнер DI еще раз приводит к тому, что будет два экземпляра этого класса.

Причиной такого дизайна является то, что у меня будет несколько реализаций IMyInterface, и позже мне нужно будет решить, какую из них использовать, но каждая реализация также должна быть контроллером для предоставления определенных конечных точек API (каждый контроллер будет предоставлять разные конечные точки,так что там не будет никаких конфликтов).

Как я могу гарантировать, что будет создан только один экземпляр моего класса, и как тогда я могу получить все реализации IMyInterface?

Ответы [ 2 ]

1 голос
/ 14 июня 2019

Насколько я понимаю, класс контроллеров создается при каждом запросе, поэтому даже если вы укажете что-то вроде этого (стиль Ninject):

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

Это будет очень плохо.Я имею в виду, что Контроллер полон состояния, и вы просто все перепутаете и нарушаете его внутренний контекст.Что вы можете сделать, это декорировать через контроллер, вместо того, чтобы самим управлять его временем жизни:

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
0 голосов
/ 14 июня 2019

Может потребоваться удалить наследование MyImpl из класса Controller.Также вам нужно рассматривать MyImpl как сервис, а не как контроллер.

Другой вариант заключается в том, что этого можно достичь с помощью контейнера 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));
}
...