Skip to content

Singleton dependencies are re-created in every dependent class #9

@FabioCastle

Description

@FabioCastle

I found out that using Dependency Injection to share a singleton service between classes doesn't work as expected.

Please, consider this simple example of PlugIn that inject the same singleton service to both a controller and an IHostedService:

using Microsoft.Extensions.DependencyInjection;
using TauriDotNetBridge.Contracts;

public class PlugIn : IPlugIn
{
    public void Initialize(IServiceCollection services)
    {
        services.AddSingleton<SharedService>();
        services.AddSingleton<DemoController>();
        services.AddSingleton<IHostedService, DemoService>();
    }
}

The SharedService class holds a reference to a common object that should be accessed both by DemoController and DemoService:

public class SharedService
{
    public SharedData? SharedData { get; set; }
}

public record SharedData(bool Initialized = false);

public class DemoController(SharedService _sharedService)
{
    public SharedData? GetData()
    {
        return _sharedService?.SharedData;
    }
}

public class DemoService(SharedService _sharedService) : IHostedService
{
    public async Task StartAsync(CancellationToken cancellationToken)
    {
        await Task.Delay(1000, cancellationToken);
        _sharedService.SharedData = new SharedData(true);

        Console.WriteLine("Shared data initialized");
    }
}

The expected behaviour is that the service should wait 1 second and then initialize the SharedData instance with a "true" value.
After that, the controller should return the JSON:

{
    "initialized": true
}

But the result will always be:

{
    "initialized": false
}

I tried to call Console.WriteLine("SharedService created") in the constructor of SharedService class and I can tell that the controller and the service will use a different instance, so that the controller can't access the initialized data.

As a workaround it's possible to define the class SharedData following the singleton pattern and make the controller and the service call static methods on it, but since I could use DI in the PlugIn class I expected to have the correct behaviour in handling this situation.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions