如何防止在启动.NET核心应用程序时多次加载依赖项?

8oomwypt  于 2022-12-14  发布在  .NET
关注(0)|答案(2)|浏览(176)

我有一个.Net Core应用程序,我们在其中使用了依赖项注入。我们所有的提供程序(我们称之为提供程序)都在Startup.cs文件中注册,并设置为services.AddTransient提供程序。我有一个控制器,它将其中一个提供程序作为依赖项注入,而该提供程序又注入了其他几个依赖项。
我遇到的问题是注入到第一个提供程序中的另一个提供程序被调用了8次。我在第二个依赖项的构造函数方法中的几行上放置了一个断点。我可以看到它被调用了8次。我检查了依赖链,找不到原因。我还逐步完成了应用程序的启动,并注意到创建了许多依赖项,这与我开始使用的提供程序无关。我是否错误地使用了依赖项注入?我只是不能'I don“我找不到为什么它会加载一个依赖项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。我们的大多数Provider也注入一个或多个依赖项。下面的代码是provider类的开始,沿着构造函数方法。希望这能解释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,但我得到了以下错误。这是repo接口,我们90%的提供程序都使用它:

InvalidOperationException: Cannot consume scoped service 'XXXXXXXSystem.Data.Entities.XXXXXXXSystemContext' from singleton 'XXXXXXXSystem.Data.Interfaces.IXXXXRepo'.

我在Startup.cs文件中的ConfigureServices(IServiceCollection服务)下设置了所有这些服务。
根据我所读到的和你们中的一些人所说的,我们的DI容器是如何设置的,这似乎是一个根本性的问题。(10或20)个提供程序加载,而索引页面只需要2个。而且,正如我所说,有些是多次加载。据我所知,它应该只加载需要的东西。2我们正在使用微软的DI容器。3我应该使用像AutoFac这样的东西来代替吗?
编辑三:我开始检查断点并查看调用堆栈,就像有人建议的那样。我们在控制器上广泛使用服务过滤器,以便拦截请求以提供公共信息。我们有一个基本过滤器,然后是一些更特定于特定控制器的其他过滤器。因此,特定的过滤器调用基本过滤器来获取一些基本信息。2我发现我们的一个过滤器正在调用一个提供程序,而那个提供程序调用了许多其他的与应用程序的初始页面无关的过滤器。
我认为这可能归结为一些糟糕的架构,因为我们有许多提供者引用了太多的其他提供者。一旦我看了过滤器,遵循依赖链就会变得混乱。
这听起来对吗?

kr98yfug

kr98yfug1#

瞬变对象总是不同的;一个新的示例被提供给每个控制器和每个服务(我假设你的情况)。
作用域对象在一个请求中是相同的,但在不同的请求中是不同的。
单例对象对于每个对象和每个请求都是相同的。

bfrts1fy

bfrts1fy2#

您可以将服务注册为Singletons,这样它们只会示例化一次:

services.AddSingleton<ISomeService, SomeService>();

相关问题