既然前面已经在启动类中注册了上下文,那么从DI容器中获取实例肯定是没问题的。于是我写了这样一句测试代码用来验证猜想:
var context = app.ApplicationServices.GetService<BloggingContext>();
不过很遗憾抛出了异常:

报错信息说的很明确,不能从root provider中获取这个服务。我从G站下载了DI框架的源码(地址是https://github.com/aspnet/Extensions/tree/master/src/DependencyInjection),拿报错信息进行反向追溯,发现异常来自于CallSiteValidator类的ValidateResolution方法:
public void ValidateResolution(Type serviceType, IServiceScope scope, IServiceScope rootScope)
{
if (ReferenceEquals(scope, rootScope)
&& _scopedServices.TryGetValue(serviceType, out var scopedService))
{
if (serviceType == scopedService)
{
throw new InvalidOperationException(
Resources.FormatDirectScopedResolvedFromRootException(serviceType,
nameof(ServiceLifetime.Scoped).ToLowerInvariant()));
}
throw new InvalidOperationException(
Resources.FormatScopedResolvedFromRootException(
serviceType,
scopedService,
nameof(ServiceLifetime.Scoped).ToLowerInvariant()));
}
}
继续往上,看到了GetService方法的实现:
internal object GetService(Type serviceType, ServiceProviderEngineScope serviceProviderEngineScope)
{
if (_disposed)
{
ThrowHelper.ThrowObjectDisposedException();
}
var realizedService = RealizedServices.GetOrAdd(serviceType, _createServiceAccessor);
_callback?.OnResolve(serviceType, serviceProviderEngineScope);
DependencyInjectionEventSource.Log.ServiceResolved(serviceType);
return realizedService.Invoke(serviceProviderEngineScope);
}
可以看到,_callback在为空的情况下是不会做验证的,于是猜想有参数能对它进行配置。把追溯对象换成_callback继续往上翻,在DI框架的核心类ServiceProvider中找到如下方法:
internal ServiceProvider(IEnumerable<ServiceDescriptor> serviceDescriptors, ServiceProviderOptions options)
{
IServiceProviderEngineCallback callback = null;
if (options.ValidateScopes)
{
callback = this;
_callSiteValidator = new CallSiteValidator();
}
//省略....
}
说明我的猜想没错,验证是受ValidateScopes控制的。这样来看,把ValidateScopes设置成False就可以解决了,这也是网上普遍的解决方案:
.UseDefaultServiceProvider(options =>
{
options.ValidateScopes = false;
})








