C# 依赖注入:无法解析作用域服务

C# 依赖注入:无法解析作用域服务,c#,asp.net-core,dependency-injection,C#,Asp.net Core,Dependency Injection,我得到以下例外情况: System.InvalidOperationException:'无法从根提供程序解析作用域服务'OSPC.Shared.Core.Data.IRepository'1[OSPC.Configuration.Objects.SignalMetaData]' 在CommandDispatcher类的ActivatorUtilities.CreateInstance行上 在调查CommandDispatcher类中注入的参数serviceProvider时,我可以在Resol

我得到以下例外情况:

System.InvalidOperationException:'无法从根提供程序解析作用域服务'OSPC.Shared.Core.Data.IRepository'1[OSPC.Configuration.Objects.SignalMetaData]' 在CommandDispatcher类的ActivatorUtilities.CreateInstance行上

在调查CommandDispatcher类中注入的参数serviceProvider时,我可以在ResolvedServices集合(所有microsoft相关服务)中看到122项,但在ConfigureServices方法中注册的服务都不在集合中

为什么我自己的注册服务没有出现

public class Startup
{
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddSingleton<ILogManager, LogManager>();
        services.AddScoped<IDbContext>(c => new OSPCContext(Configuration.GetConnectionString("OSPCConnectionstring")));
        services.AddScoped(typeof(IRepository<>), typeof(EfRepository<>));
        services.AddSingleton<ICommandDispatcher, CommandDispatcher>();
    }
}



public class CommandDispatcher : ICommandDispatcher
{
    private readonly IServiceProvider _serviceProvider;
    private readonly Dictionary<string, Type> _registeredCommands = new Dictionary<string, Type>();

    public CommandDispatcher(IServiceProvider serviceProvider)
    {
        _serviceProvider = serviceProvider;
        _registeredCommands.Add("CreateSignalMetaData", typeof(CreateSignalMetaDataHandler));
        _registeredCommands.Add("CreatePDCQueryConfig", typeof(CreatePDCQueryConfigHandler));
    }

    public object Dispatch(string json)
    {
        JObject jObject = JObject.Parse(json);
        JToken jToken = jObject["type"];
        if (jToken == null)
        {
            throw  new Exception("The parameter type is missing in the JSON string (Pay attention: it is casse sensitive).");

        }
        Type typeCommandHandler = _registeredCommands[jToken.ToString()];
        dynamic commandHandler = ActivatorUtilities.CreateInstance(_serviceProvider, typeCommandHandler);
        dynamic o = jObject.ToObject(commandHandler.InputType);
        return commandHandler.Handle(o);
    }
}



[Route("api/[controller]")]
[ApiController]
public class ConfigurationController : ControllerBase
{
    private readonly ILog _logger;
    private readonly IConfigurationService _configurationService;
    private readonly ICommandDispatcher _commandDispatcher;

    public ConfigurationController(ICommandDispatcher commandDispatcher)
    {
        this._commandDispatcher = commandDispatcher;
    }

    // POST api/configuration
    [HttpPost]
    public IActionResult Post([FromBody] dynamic  json)
    {
        var result = _commandDispatcher.Dispatch(json.ToString());                
        return Ok(result);
    }
}

using OSPC.Configuration.Msg;
using OSPC.Configuration.Objects;
using OSPC.Shared.Core.Commands;
using OSPC.Shared.Core.Data;
using System.Collections.Generic;

namespace OSPC.Configuration.CommandHandler
{
    public class CreateSignalMetaDataHandler : CommandHandlerBase<CreateSignalMetaDataRequest, CreateSignalMetaDataResponse>
    {
        private readonly IRepository<SignalMetaData> _signalMetaDataRepository;

        public CreateSignalMetaDataHandler(IRepository<SignalMetaData> signalMetaDataRepository)
        {
            _signalMetaDataRepository = signalMetaDataRepository;
        }

        public override CreateSignalMetaDataResponse Handle()
        {            
            Output.Success = false;

            var result = new CreateSignalMetaDataResponse
            {
                SignalMetaDatas = new List<CreateSignalMetaDataResponse.SignalMetaData>()
            };

            foreach (var item in Input.Payload.SignalMetaDatas)
            {
                var signalMetaData = new Objects.SignalMetaData()
                {
                    SignalName = item.SignalName,
                    Unit = item.Unit,
                    SignalDescription = item.SignalDescription,
                    Source = item.Source
                };
                _signalMetaDataRepository.Insert(signalMetaData);

                result.SignalMetaDatas.Add(new CreateSignalMetaDataResponse.SignalMetaData()
                {
                    Id = signalMetaData.Id,
                    SignalName = signalMetaData.SignalName,
                    Unit = signalMetaData.Unit,
                    SignalDescription = signalMetaData.SignalDescription,
                    Source = signalMetaData.Source
                });
            }

            Output.Success = true;        

            return result;
        }
    }
}
公共类启动
{
public void配置服务(IServiceCollection服务)
{
services.AddSingleton();
addScope(c=>newOSPCContext(Configuration.GetConnectionString(“OSPCConnectionstring”));
addScope(typeof(IRepository)、typeof(eRepository));
services.AddSingleton();
}
}
公共类CommandDispatcher:ICommandDispatcher
{
私有只读服务器ViceProvider\u服务提供商;
专用只读词典_registeredCommand=new Dictionary();
公共命令调度器(IServiceProvider服务提供程序)
{
_服务提供者=服务提供者;
_Add(“CreateSignalMetaData”,typeof(CreateSignalMetaDataHandler));
_Add(“CreatePDCQueryConfig”,typeof(CreatePDCQueryConfigHandler));
}
公共对象分派(字符串json)
{
JObject=JObject.Parse(json);
JToken JToken=jObject[“类型”];
如果(jToken==null)
{
抛出新异常(“JSON字符串中缺少参数类型(请注意:它对CASE敏感)。”;
}
类型typeCommandHandler=_registeredCommand[jToken.ToString()];
dynamic commandHandler=ActivatorUtilities.CreateInstance(_serviceProvider,typeCommandHandler);
动态o=jObject.ToObject(commandHandler.InputType);
返回commandHandler.Handle(o);
}
}
[路由(“api/[控制器]”)]
[ApiController]
公共类配置控制器:ControllerBase
{
专用只读ILog_记录器;
专用只读IConfigurationService\u配置服务;
专用只读ICommandDispatcher\u commandDispatcher;
公共配置控制器(ICommandDispatcher commandDispatcher)
{
这是._commandDispatcher=commandDispatcher;
}
//后api/配置
[HttpPost]
public IActionResult Post([FromBody]动态json)
{
var result=_commandDispatcher.Dispatch(json.ToString());
返回Ok(结果);
}
}
使用OSPC.Configuration.Msg;
使用OSPC.Configuration.Objects;
使用OSPC.Shared.Core.Commands;
使用OSPC.Shared.Core.Data;
使用System.Collections.Generic;
命名空间OSPC.Configuration.CommandHandler
{
公共类CreateSignalMetaDataHandler:CommandHandlerBase
{
私有只读IRepository\u signalMetaDataRepository;
公共CreateSignalMetaDataHandler(IRepository signalMetaDataRepository)
{
_signalMetaDataRepository=signalMetaDataRepository;
}
公共重写CreateSignalMetaDataResponse句柄()
{            
Output.Success=false;
var result=new CreateSignalMetaDataResponse
{
SignalMetaDatas=新列表()
};
foreach(Input.Payload.SignalMetaDatas中的变量项)
{
var signalMetaData=新对象。signalMetaData()
{
SignalName=项。SignalName,
单位=项目。单位,
SignalDescription=项目。SignalDescription,
Source=项目。Source
};
_signalMetaDataRepository.Insert(signalMetaData);
result.SignalMetaDatas.Add(新建CreateSignalMetaDataResponse.SignalMetaData())
{
Id=signalMetaData.Id,
SignalName=signalMetaData.SignalName,
单位=信号元数据。单位,
SignalDescription=signalMetaData.SignalDescription,
Source=signalMetaData.Source
});
}
Output.Success=true;
返回结果;
}
}
}
对于
IRepository
,它是有范围的,对于
ICommandDispatcher
,它是单例的。对于
ActivatorUtilities.CreateInstance(\u serviceProvider,typeCommandHandler)
\u serviceProvider
是无法解析作用域服务的根提供程序

尝试下面的代码创建一个新的作用域提供程序

dynamic commandHandler = ActivatorUtilities.CreateInstance(
    _serviceProvider.CreateScope().ServiceProvider, typeCommandHandler);
对于
IRepository
,它是有范围的;对于
ICommandDispatcher
,它是单例的。对于
ActivatorUtilities.CreateInstance(\u serviceProvider,typeCommandHandler)
\u serviceProvider
是无法解析作用域服务的根提供程序

尝试下面的代码创建一个新的作用域提供程序

dynamic commandHandler = ActivatorUtilities.CreateInstance(
    _serviceProvider.CreateScope().ServiceProvider, typeCommandHandler);

Tao Zhou的解决方案正在发挥作用,但我不知道这个解决方案是否也解决了俘虏依赖问题

我用以下方法解决了这个问题: 在startup类中,我将其改为AddScope,而不是AddSingleton

  services.AddScoped<ICommandDispatcher, CommandDispatcher>();
services.addScope();
否则,我将面临捕获依赖性问题()

我们不能将其定义为Singleton(CommandDispatcher),因为否则我们会有一个俘虏依赖性问题,因为CommandDispatcher最终将实例化CommandHandler(f.e.CreateSignalMetaDataHandler),并且在构造函数中必须注入一个或多个eRepositories,而这些eRepositories又必须注入DbContext。 其目的是DbContext的实例化必须限定范围。因此,每个HTTP请求必须有且只有一个实例o