ASP.NET Dependency Injection Scoped время жизни - PullRequest
0 голосов
/ 01 января 2019

Я использую ASP.Net Core Inpendency Injection в приложении MVC (не приложение .Net Core, а классический ASP.NET MVC Applicatio). Я использую DI, добавляя пакет Nuget в Microsoft.Extensions.DependencyInjection.Я пытаюсь создать срок службы для своих контроллеров, поэтому у меня появляется новая область видимости, когда я создаю свои контроллеры, но всегда получаю один и тот же экземпляр для своих запросов, и возникает ошибка, как показано ниже. «Один экземпляр контроллера» X.Controllers.HomeController 'нельзя использовать для обработки нескольких запросов. Если используется фабрика пользовательских контроллеров, убедитесь, что она создает новый экземпляр контроллера для каждого запроса "

Я использовал собственную фабрику для создания своейконтроллеры и использовали новую область для создания контроллеров.и область действия расположена в методе ReleaseController

public class MyServiceFactory : DefaultControllerFactory
{
        private readonly IServiceContainer _dependencyManager;

    public MyServiceFactory (IServiceContainer dependencyManager)
    {
            this._dependencyManager = dependencyManager;
    }

    public override void ReleaseController(IController controller)
    {
        _dependencyManager.Release(((ServiceEndPoint)controller).Context.RuntimeContext.Scope);
    }


    protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
    {


            if (controllerType == null)
            {
                throw new HttpException(404, string.Format("The controller for path '{0}' could not be found.", requestContext.HttpContext.Request.Path));
            }
            var scope = _dependencyManager.GetNewScope();
            var service=(ServiceEndPoint)_dependencyManager.Resolve(scope, controllerType);
            service.Context.RuntimeContext.SetScope(scope);
            return service;
    }
}

. ServiceEndpoint - это просто базовый класс, производный от Controller, и я использую его в качестве основы для всех моих контроллеров, который содержит некоторую общую логику.Я устанавливаю контекст для моих контроллеров, который также содержит только что созданную область, и я удаляю свою область в Releasecontroller, получая его из контекста._dependencyManager.GetNewScope () создайте новую область видимости, как показано ниже:

   return _container.CreateScope(); 

, где _container - это экземпляр IServiceProvider

Код _dependencyManager.Resolve (scope, type), как показано ниже

    public object Resolve(IServiceScope scope,Type type)
    {
        return scope.ServiceProvider.GetService(type);
    }

1 Ответ

0 голосов
/ 01 января 2019

Вы делаете что-то не так, но поскольку вы скрыли использование контейнера Microsoft.Extensions.DependencyInjection (MS.DI) за своей собственной абстракцией, невозможно увидеть, что происходит.

Однакониже приведен пример рабочего примера приложения, которое интегрирует ASP.NET MVC с MS.DI.

фабрикой контроллера, специфичной для MS.DI:

public class MsDiControllerFactory : DefaultControllerFactory
{
    private readonly ServiceProvider container;

    public MsDiControllerFactory(ServiceProvider container) => this.container = container;

    protected override IController GetControllerInstance(RequestContext c, Type type) =>
        (IController)this.GetScope().ServiceProvider.GetRequiredService(type);

    public override void ReleaseController(IController c) => this.GetScope().Dispose();

    private IServiceScope GetScope() =>
       (IServiceScope)HttpContext.Current.Items["scope"] ??
          (IServiceScope)(HttpContext.Current.Items["scope"] = this.container.CreateScope());
}

Приложение MVC, конфигурирующее контейнери замена фабрики контроллеров по умолчанию:

public class MvcApplication : System.Web.HttpApplication
{
    protected void Application_Start()
    {
        // Default MVC stuff
        AreaRegistration.RegisterAllAreas();
        FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
        RouteConfig.RegisterRoutes(RouteTable.Routes);
        BundleConfig.RegisterBundles(BundleTable.Bundles);

        // create container builder to register dependencies in
        var services = new ServiceCollection();

        // register controller in the controller
        services.AddScoped<HomeController>();

        // Build the container while ensuring scopes are validated
        ServiceProvider container = services.BuildServiceProvider(true);

        // Replace default controller factory
        ControllerBuilder.Current.SetControllerFactory(
            new MsDiControllerFactory(container)); 
    }
}

Когда вы примените вышеуказанный код к приложению MVC, созданному с использованием шаблона MVC по умолчанию для Visual Studio, вы получите работающее приложение MVC, которое использует MS.DI какего контейнер приложений.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...