.NET application doesn't run after injecting a Scoped service into a Singleton

problem

I tried to inject a repository (service that uses DbContext to communicate with the database) into an Arduino communication service. The former has a Scoped lifetime because it is short-lived and instantiated on a per-request basis, every time it is needed, while the latter is Singleton because it's required to keep a persistent connection with the Arduino board during program execution.

Injecting it like this causes an unhandled exception, because it can lead to unexpected behaviours such as memory leaks, stale data etc. Changing the lifetime of either is not possible as it leads to other problems.

public ArduinoCommunicationService(IRoomsRepository roomsRepository)
{
    _roomsRepository = roomsRepository;
}
solution

Create a factory, inject it into the singleton service and request the scoped service from the factory.

namespace TestRooms.Repositories.Interface
{
    public interface IRoomsRepositoryFactory
    {
        IRoomsRepository CreateRepository();
    }
}
using TestRooms.Repositories.Interface;

namespace TestRooms.Repositories.Implementation
{
    public class RoomsRepositoryFactory : IRoomsRepositoryFactory
    {
        private readonly IServiceProvider _serviceProvider;

        public RoomsRepositoryFactory(IServiceProvider serviceProvider)
        {
            _serviceProvider = serviceProvider;
        }

        public IRoomsRepository CreateRepository()
        {
            var scope = _serviceProvider.CreateScope();
            return scope.ServiceProvider.GetRequiredService<IRoomsRepository>();
        }
    }
}
public ArduinoCommunicationService(IRoomsRepositoryFactory roomsRepositoryFactory)
{
    _roomsRepositoryFactory = roomsRepositoryFactory;
}
...
var roomsRepository = _roomsRepositoryFactory.CreateRepository();
Gravatar
Author: andreiflorin-c
Last Edit: August 2, 2024

1 Comment


Very nicely written!

I haven't tried to do this exactly, but one thing that might be missing: did you also need to register the factory at start-up, doing something like: services.AddSingleton<IRoomsRepositoryFactory, RoomsRepositoryFactory>(); ?

If so, you could add how you did it, for completeness. You should be able to edit your post.

Gravatar
Dan Dumitru
Aug 3, 2024 at 08:26

Last Edit August 2, 2024
Created August 2, 2024
Views 74
Tags
.NET
C#

Join us!

Do you like this website?

Bookmark it and come back here to write a post yourself when you run into something shareable.

Early collaborators will get to own a part of the project (5 to 20%)... >> read more

Your Comment

Feel free to post additional info or improvement suggestions.
preview
Optional, never shown, displays gravatar.

Formatting Tips

This editor uses Markdown to easily add code in your posts.

Triple backticks for full line(s) of code (or indent 4 spaces)

```
let foo = 'bar';
```

[link text](http://a.com)

*italic* **bold**

More Tips