[英]Dependecy Injection : Cannot resolve scoped service
我得到以下異常:
'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;
}
}
}
對於IRepository<>
,它是作用域的;對於ICommandDispatcher
,它是單例的。 對於ActivatorUtilities.CreateInstance(_serviceProvider, typeCommandHandler);
, _serviceProvider
是無法解析作用域服務的根提供者。
嘗試下面的代碼創建一個新的作用域提供程序。
dynamic commandHandler = ActivatorUtilities.CreateInstance(
_serviceProvider.CreateScope().ServiceProvider, typeCommandHandler);
淘周的解決方案正在工作,但我不知道該解決方案是否還解決了圈養依賴性問題?
我已通過以下方式解決了該問題:在啟動類中,我已將其更改為AddScoped而不是AddSingleton
services.AddScoped<ICommandDispatcher, CommandDispatcher>();
否則,我會遇到專屬依賴性問題( https://andrewlock.net/the-dangers-and-gotchas-of-using-scoped-services-when-configuring-options-in-asp-net-core/ )。
我們不能將其定義為Singleton(CommandDispatcher),因為否則,我們會遇到圈養依賴性問題,因為CommandDispatcher最終將實例化CommandHandler(fe CreateSignalMetaDataHandler),並且在構造函數中必須注入一個或多個EFRepository,而它們又必須具有DbContext注射。 目的是必須限制DbContext的實例化。 因此,每個HTTP請求必須注入一個DbContext實例,並且只有一個實例被注入。 因此,如果我們使用不同的存儲庫,那么它們都必須共享相同的DbContext。 每個HTTP請求都有其自己的DbContext,並且不同的HTTP請求將具有不同的DbContext。 因為必須限制DbContext的范圍,所以也必須一直限制CommandDispatcher的范圍,以避免俘虜依賴性問題。 因此CommandDispatcher不能定義為Singleton。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.