当我像这样为IPersonProvider注册工厂时:
services.AddScoped<IPersonProvider, PersonProvider>();
services.AddSingleton<Func<IPersonProvider>>(sp => () => sp.GetService<IPersonProvider>());
我遇到错误:
InvalidOperationException:无法从根提供者解析作用域服务'DependencyApp.Provider.IPersonProvider'。
我知道我无法解析具有Scoped依赖项的Singleton对象,但是据我了解,我的工厂没有任何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的依赖项。
答案 0 :(得分:1)
出现此问题的原因是由于使用了IServiceProvider
实例。将服务注册为单例时,根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
的问题,而是以下事实:提供者是根源。
答案 1 :(得分:0)
我已经按照其正常工作完成了
services.AddSingleton<ITokenManager, TokenManger>();
services.AddScoped<ITokenProvider, TokenProvider>();
public class TokenProvider : ITokenProvider
{
private readonly ITokenManager _tokenManager;
public TokenProvider(ITokenManager tokenManager)
{
_tokenManager = tokenManager;
}
}