Регистрация Transient Web API Controller с IServiceProvider приводит к исключению из памяти - PullRequest
0 голосов
/ 27 сентября 2018

Я видел множество примеров настройки веб-API .NET Framework с использованием библиотек DI, созданных для .NET Core (т. Е. IServiceProvider).Хотя все это имеет смысл, я вижу проблемы с памятью с моими контроллерами Web API.Описание этой настройки показано здесь.

asp.net добавление ApiController в качестве службы для внедрения зависимостей

IServiceProvider использует временное отслеживание и хранит список всех одноразовых объектов.Поскольку базовый класс ApiController реализует IDisposable и настроен как временная зависимость, список одноразовых элементов будет неограниченно увеличиваться по мере поступления последующих запросов к каждому контроллеру.Это создаст очень большую проблему с памятью.Здесь описывается временное отслеживание.

https://github.com/aspnet/DependencyInjection/issues/456

Мой вопрос: как правильно зарегистрировать эти контроллеры в контейнере, чтобы память не вышла из-под контроля?

Мне нужно использовать IServiceProvider, и я не могу использовать стороннюю платформу DI.

Я попытался зарегистрировать контроллеры в качестве области, но получил следующую ошибку.Любая помощь будет оценена.

Сообщение об ошибке контроллера области действия

1 Ответ

0 голосов
/ 29 ноября 2018

Ответ заключался в создании экземпляра класса, реализующего IDependencyScope, из метода BeginScope () в DependencyResolver.Это предотвращает добавление нового указателя в коллекцию Disposables и тем самым устраняет утечку памяти.

/// <inheritdoc />
public class DefaultDependencyResolver : IDependencyResolver
{
    private readonly IServiceProvider _serviceProvider;

    /// <inheritdoc />
    public DefaultDependencyResolver(IServiceProvider serviceProvider)
    {
        _serviceProvider = serviceProvider;
    }

    /// <inheritdoc />
    public object GetService(Type serviceType)
    {
        return _serviceProvider.GetService(serviceType);
    }

    /// <inheritdoc />
    public IEnumerable<object> GetServices(Type serviceType)
    {
        return _serviceProvider.GetServices(serviceType);
    }

    /// <inheritdoc />
    public IDependencyScope BeginScope()
    {
        return new DefaultDependencyScope(_serviceProvider.CreateScope());
    }

    /// <inheritdoc />
    public void Dispose()
    {
        //No-op
    }
}

/// <inheritdoc />
public class DefaultDependencyScope : IDependencyScope
{
    private readonly IServiceScope _serviceScope;

    /// <inheritdoc />
    public DefaultDependencyScope(IServiceScope serviceScope)
    {
        _serviceScope = serviceScope;
    }

    /// <inheritdoc />
    public void Dispose()
    {
        _serviceScope.Dispose();
    }

    /// <inheritdoc />
    public object GetService(Type serviceType)
    {
        return _serviceScope.ServiceProvider.GetService(serviceType);
    }

    /// <inheritdoc />
    public IEnumerable<object> GetServices(Type serviceType)
    {
        return _serviceScope.ServiceProvider.GetServices(serviceType);
    }
}

, а затем регистрирует преобразователь зависимостей из конфигурации API

        //Register controllers with container
        foreach (var type in typeof(WebApiConfig).Assembly.GetExportedTypes()
            .Where(t => !t.IsAbstract && !t.IsGenericTypeDefinition)
            .Where(t => typeof(ApiController).IsAssignableFrom(t)))
        {
            services.AddTransient(type);
        }

        //Link DI in application to container
        var provider = services.BuildServiceProvider();

        config.DependencyResolver = new DefaultDependencyResolver(provider);

В моем случаеМне не нужно регистрировать какие-либо зависимости как синглтоны.Если это требуется, может потребоваться дополнительный код для условного возврата области видимости, основанной на типе.

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