2

I have a Repository service that should be Transient. It is used in many applications.

I have a new application that's a Console App, and current guidance suggests implementing my business logic in Worker Services and adding them to the Generic Host with AddHostedService<MyService>() calls.

One of those Worker Services uses that Repository, so I'm also adding the Repository to my dependency injection container. Thus:

builder.AddTransient<IRepository,Repository>();
builder.AddHostedService<MyService>();

This fails under .NET Core 3.1 because it won't let a Singleton consume a Transient service. That makes sense; you don't want the Transient service to vanish when you might want to use it later. But I didn't ask for a Singleton! What's going on?

The answer is that in .NET Core 2.2 AddHostedService creates a Transient service but in .NET Core 3.1 it creates a Singleton service. The official line is that if your Worker Service needs to consume a Transient service you should just instantiate a new Service Scope and implement... a service locator? Really? So now I can't use regular dependency injection in the service constructor?

Microsoft's rationale for making Worker Services Transient prior to .NET Core 3.x seems solid to me: You only instantiate them once, so there's no need to force you into a Singleton pattern.

So my question has a few parts:

  • Is Microsoft really asking me to apply a Service Locator in places where it wasn't called for until .NET Core made stuff weird?
  • Do I have to rewrite all my Worker Services to work with .NET Core 3.x now?
  • Doesn't this Service Locator strategy circumvent the reason why they prevented Singletons from consuming Transient services in the first place?

My point, and I do have one, is that don't understand why Microsoft imposes a Singleton pattern on the Worker Service that makes it impossible for it to consume Transient services and then recommends a workaround that a) is a well-known antipattern; and b) exactly undermines the utility of not allowing Singletons to consume Transients in the first place.

What is going on here that I don't understand?

7
  • 1
    I think this is a matter of opinion. Personally I think its better to register the HostedService as a Singelton because that is more or less what it is. Furthermore I don´t think that the "Service Locator"-Pattern is by definition a anti pattern. It depends on the use case and in your situation it is ok to use it. I can understand that it is frustrating to change code.
    – Darem
    Mar 15, 2021 at 7:46
  • The new architecture takes a thing that already works (Transient Worker Services that only get instantiated once), then adds complexity that breaks existing code and delivers no new value. What can I do now with Singleton Worker Services that I couldn't already do? Nothing. Is it making anything simpler or more efficient? No. Does it make my code more reusable? No, it makes it less reusable. There must be some tradeoff here, some benefit to forcing a Singleton Worker pattern, but I can't figure out what it is.
    – catfood
    Mar 15, 2021 at 17:05
  • 1
    Correct me if I am wrong! But I think there is a benefit in adding the service as a singelton. You can now inject the service into your controller and exchange data for example. You could do that before but you have to use extra classes for that.
    – Darem
    Mar 16, 2021 at 7:01
  • 1
    Aha! Now there's a use case for Singleton Worker Services. I'm afraid Microsoft broke my best use case doing it though.
    – catfood
    Mar 17, 2021 at 14:50
  • 1
    Sorry for that! Hopefully you find a solution to make it work again!
    – Darem
    Mar 17, 2021 at 14:51

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.