.NET Core:如何在IHostedService间引用且避免重复实例?
AddHostedService Can't Resolve Your Domain Dependency for ComplianceService Let's break down exactly what's happening here, and how to fix it cleanly:
The Root Cause
When you use serviceCollection.AddHostedService<Domain>(), you're not registering Domain as a resolvable service type in the DI container—you're only registering it as an implementation of IHostedService.
Under the hood, AddHostedService<T> does something like this:
services.AddSingleton<IHostedService, T>();
This means the container knows how to provide an IHostedService instance (which happens to be a Domain), but it has no idea how to resolve a direct request for the Domain type itself. That's why when ComplianceService tries to inject a Domain in its constructor, the container throws that InvalidOperationException—it can't find a registered service for Domain.
Why Your Temporary Fix Creates Two Instances
When you added serviceCollection.AddSingleton<Domain>(), you told the container how to resolve Domain directly. But then AddHostedService<Domain>() still creates a second Domain instance, because it's registering a new IHostedService implementation separate from your singleton Domain registration.
Your workaround using AddHostedService(sp => sp.GetRequiredService<Domain>()) fixes this by reusing the singleton instance, but it feels clunky because you're manually wiring things up.
The Clean, Intuitive Solution
The fix is straightforward: register Domain as a singleton first, then use it as your hosted service. This way, the DI container knows how to resolve Domain for ComplianceService, and you only get one instance running as a hosted service.
Here's the corrected code:
// First, register Domain as a singleton so the container can resolve it for dependencies serviceCollection.AddSingleton<Domain>() // Keep your other dependency registrations .AddSingleton<RulesActivator>() .AddSingleton<Accruals>() .AddSingleton<IRuleRepository, ComplianceRuleRepository>() .AddSingleton<IViolation, Violation>(); // Now add Domain as a hosted service by reusing the singleton instance serviceCollection.AddHostedService(sp => sp.GetRequiredService<Domain>()); // Conditionally add ComplianceService as before if (this.Configuration.GetValue<bool>("ComplianceEnabled")) { serviceCollection.AddHostedService<ComplianceService>(); }
This approach:
- Lets
ComplianceServicesuccessfully injectDomain(since it's registered in the container) - Ensures only one
Domaininstance exists (both the hosted service andComplianceServiceuse the same singleton) - Follows DI best practices by making your service registrations explicit and intuitive
Key Takeaway
AddHostedService<T> is for registering something as a background service, not for making that type available as a dependency to other services. If you need a hosted service to be injectable elsewhere, you must first register the type itself in the DI container, then reference that registered instance when adding it as a hosted service.
内容的提问来源于stack exchange,提问作者Don Airey

