我有一个。net Core应用程序,我们使用依赖注入。我们所说的所有提供者都在Startup.cs文件中注册,并被设置为服务。AddTransient提供者。我有一个控制器,它注入了其中一个提供商作为依赖项,而该提供商又注入了其他一些依赖项。
我遇到的问题是,注入到第一个提供程序中的其他提供程序之一被调用了8次。我在第二个依赖项的构造函数方法的几行中放置了一个断点,我可以看到它被调用了8次。我查看了依赖性链,却找不到原因。我还逐步浏览了应用程序的开始部分,并注意到创建了许多依赖项,这些依赖项与我开始使用的提供程序无关。我是否错误地使用了依赖注入?我只是找不到一个解释,为什么它会加载一个依赖8次。
这是我的创业课程的一部分,如果它有帮助的话。
services.AddTransient<IResourceProvider, ResourceProvider>();
services.AddTransient<IStaticListProvider, StaticListProvider>();
services.AddTransient<IPlanActivityLineItemProvider, PlanActivityLineItemProvider>();
services.AddTransient<IPlanRevisionProvider, PlanRevisionProvider>();
services.AddTransient<IProjectImportExportProvider, ProjectImportExportProvider>();
services.AddTransient<IExpandoParserProvider, ExpandoParseProvider>();
services.AddTransient<IProjectPlanProvider, ProjectPLanProvider>();
services.AddTransient<IActualsImportProvider, ActualsImportProvider>();
services.AddTransient<IReportProvider, ReportProvider>();
services.AddTransient<IProjectWorkFlowProvider, ProjectWorkflowProvider>();
编辑:对不起,我没有提供足够的代码来帮助解决这个问题。我们的控制器接受了一个依赖,我们称这个类为Provider。我们的大多数提供商也注入一个或多个依赖项。下面的代码是提供程序类的开头,以及构造函数方法。希望这解释了提供者问题。我在构造函数的一行上放置了一个断点,当应用程序启动时,它在这个断点处停止了8次,这使我相信它实例化了8次提供程序。我也找不到理由。我遵循依赖链,它不会在另一个提供商中再次被调用。我看不出有什么合理的解释。当应用程序启动时,每个服务都实例化了吗?
private readonly IURCSRepo _repo;
private readonly IPlanRevisionProvider _planRevisionProvider;
private readonly IExcelFileAndSheetValidationProvider _excelImportValidationProvider;
private readonly IExcelExtensionsProvider _excelExtensionsProvider;
private readonly IEmailProvider _emailProvider;
private readonly string _rpmActuals = "Actuals";
private TableParser<ActualHoursLineItemImportModel> _rpmLineItemTableParser;
private List<RoleDescriptionModel> roleModels = new List<RoleDescriptionModel>();
private List<PlanResourceModel> resources = new List<PlanResourceModel>();
private List<ProjectPlanHeaderModel> projectPlanHeaders = new List<ProjectPlanHeaderModel>();
private List<ChargingStrategyModel> chargingStrategies = new List<ChargingStrategyModel>();
private List<HoursTypeModel> hoursTypes = new List<HoursTypeModel>();
private readonly UserManager<ApplicationUser> _userManager;
public ActualsImportProvider(IURCSRepo uRCSRepo, IPlanRevisionProvider planRevisionProvider, IExcelFileAndSheetValidationProvider excelFileAndSheetValidationProvider, IExcelExtensionsProvider excelExtensionsProvider, IEmailProvider emailProvider, UserManager<ApplicationUser> userManager)
{
_repo = uRCSRepo;
_planRevisionProvider = planRevisionProvider;
_excelImportValidationProvider = excelFileAndSheetValidationProvider;
_excelExtensionsProvider = excelExtensionsProvider;
_rpmLineItemTableParser = new TableParser<ActualHoursLineItemImportModel>(_excelExtensionsProvider);
_emailProvider = emailProvider;
roleModels = _repo.GetAllRoleDescriptions(true).MakeRoleDescriptions();
resources = _repo.GetAllActiveResources().MakePlanResources();
projectPlanHeaders = _repo.GetAllProjectPlanHeaders().MakeProjectPlanHeaderList();
chargingStrategies = _repo.GetAllChargingStrategies().MakeChargingStrategies();
hoursTypes = _repo.GetAllHoursTypes(true).MakeHoursTypes();
_userManager = userManager;
}
编辑2:我试图将服务设置为AddSingleton,我得到了以下错误。这是回购接口,90%的提供商都使用它:
InvalidOperationException: Cannot consume scoped service 'XXXXXXXSystem.Data.Entities.XXXXXXXSystemContext' from singleton 'XXXXXXXSystem.Data.Interfaces.IXXXXRepo'.
我正在Startup.cs文件中设置所有这些,在ConfigureServices(IServiceCollection services)下。
根据我所读到的和你们中的一些人所说的,我们的DI容器的设置似乎存在一个基本问题。我这么说是因为有太多(10或20)提供程序需要加载,而索引页只需要2个。我说过,有些会多次加载。据我所知,它应该只加载需要的东西。我们正在使用微软的DI容器。我应该用AutoFac之类的东西吗?
编辑3:我开始检查断点并查看调用堆栈,就像有人建议的那样。我们在控制器上广泛使用服务过滤器,以便拦截提供常见信息的请求。我们有一个基本的过滤器,还有一些其他的过滤器是针对特定控制器的。特定的过滤器调用基过滤器来获取一些基本信息。我发现我们的一个过滤器调用了一个提供程序,而这个提供程序调用了许多与应用程序的初始页面无关的其他过滤器。我认为这可能归结于一些糟糕的架构,因为我们有太多的提供者引用了太多的其他提供者。当我看到过滤器时,遵循依赖链会让人感到困惑。
这听起来对吗?
瞬态对象总是不同的;一个新的实例被提供给每个控制器和每个服务(我假设是你的情况)。
作用域对象在一个请求内是相同的,但在不同的请求之间是不同的。
单例对象对于每个对象和每个请求都是相同的。
你可以将你的服务注册为singleton,这样它们只被实例化一次:
services.AddSingleton<ISomeService, SomeService>();