Как зарегистрировать одноуровневое фабричное разрешение объектов в ASP.NET Core? - PullRequest
1 голос
/ 14 мая 2019

Когда я регистрирую фабрику для IPersonProvider следующим образом:

services.AddScoped<IPersonProvider, PersonProvider>();
services.AddSingleton<Func<IPersonProvider>>(sp => () => sp.GetService<IPersonProvider>());

Я получаю сообщение об ошибке:

InvalidOperationException: Невозможно разрешить службу с ограниченным доступом 'DependencyApp.Provider.IPersonProvider' от корневого поставщика.

Мне известно, что я не могу разрешить объект Singleton с зависимостями Scoped, но, как я понимаю, у моей фабрики нет никаких зависимостей Scoped - на самом деле у нее нет никаких зависимостей. Он просто создает объекты, когда я спрашиваю, как это:

public class HomeController : Controller
{
    private readonly Func<IPersonProvider> _factory;

    public HomeController(Func<IPersonProvider> factory)
    {
        _factory = factory;
    }

    [Route("/")]
    public string Calculate()
    {
        var personProvider = _factory();
        //.
        //.
        //.

        return "test";
    }
}

Почему я получаю эту ошибку тогда? Как решить проблему? Я считаю, что регистрация фабрики в качестве Singleton, которая может существовать до тех пор, пока у всего приложения не должно возникнуть никаких проблем при создании объектов с областью видимости - в конечном итоге эти созданные объекты на самом деле не являются зависимостями от Singleton.

Ответы [ 2 ]

1 голос
/ 14 мая 2019

Причиной возникновения этой проблемы является использование экземпляра IServiceProvider. Когда вы регистрируете сервис как singleton, корень IServiceProvider передается заводскому методу.

Итак, когда у вас есть:

services.AddSingleton<Func<IPersonProvider>>(sp => () => sp.GetService<IPersonProvider>());

Это означает, что sp должен быть совместим с временем жизни синглтона, которое является только корневым поставщиком услуг.

Чтобы проиллюстрировать, что я имею в виду.

using (var scopedServiceProvider = sp.CreateScope())
{
    scopedServiceProvider.GetService<IPersonProvider>(); // valid

    sp.GetService<IPersonProvider>(); // not valid
}

Однако, когда ваш фабричный метод имеет временное время жизни, переданный sp больше не использует корневого поставщика услуг и вместо этого использует производного, где ограничение на создание экземпляров сервисов с ограниченным доступом не применяется.

Чтобы повторить проблему, используемый вами sp не может создавать сервисы с определенной областью, поэтому дело не в том, что возвращаемая служба является Func, а в том, что провайдер является корень один.

0 голосов
/ 14 мая 2019

Я выполнил следующие действия:

 services.AddSingleton<ITokenManager, TokenManger>();
 services.AddScoped<ITokenProvider, TokenProvider>();

public class TokenProvider : ITokenProvider
{
    private readonly ITokenManager _tokenManager;
    public TokenProvider(ITokenManager tokenManager)
    {
        _tokenManager = tokenManager;
    }
}
...