Dependency Injection on a class instantiation of a sealed class

2.4k Views Asked by At

I'm currently trying to build a sealed class that gets the configuration of the azure storage via settings stored in a JSON. I register the settings in the startup.cs class, and then inject it to the constructor. The problem is when I need to initiate the same class within the class because its a sealed class

public sealed class AzureFileStorage
{
    private static volatile AzureFileStorage instance;
    private static object syncRoot = new Object();
    private readonly AzureBlobSettings _azureBlobSettings;

    public CloudStorageAccount StorageAccount { get; private set; }
    public CloudBlobClient BlobClient { get; private set; }
    public CloudBlobContainer Container { get; private set; }

    public AzureFileStorage(IOptions<AzureBlobSettings> fbAuthSettingsAccessor)
    {
        _azureBlobSettings = fbAuthSettingsAccessor.Value;
        StorageAccount = CloudStorageAccount.Parse(_azureBlobSettings.BlobStorageConnectionString);

        //instantiate the client
        BlobClient = StorageAccount.CreateCloudBlobClient();

        //set the container
        Container = BlobClient.GetContainerReference(_azureBlobSettings.ContainerBlobAzureId);

    }

    public static AzureFileStorage Instance
    {
        get
        {
            if (instance == null)
            {
                lock (syncRoot)
                {

                    if (instance == null)
                        instance = new AzureFileStorage(????);
                }
            }

            return instance;
        }
    }
}

How do I initiaze azurefilestorage, if the azureblobsettings are being passed via dependency injection.

1

There are 1 best solutions below

0
On

As already alluded to by a commenter, the current design does not lend itself well to dependency injection.

The AzureFileStorage class should be refactored to remove the singleton instance and additionally having it's own abstraction.

public interface IAzureFileStorage {
    CloudStorageAccount StorageAccount { get; }
    CloudBlobClient BlobClient { get; }
    CloudBlobContainer Container { get; }
}

public sealed class AzureFileStorage : IAzureFileStorage {
    private readonly AzureBlobSettings _azureBlobSettings;


    public AzureFileStorage(IOptions<AzureBlobSettings> fbAuthSettingsAccessor) {
        _azureBlobSettings = fbAuthSettingsAccessor.Value;
        StorageAccount = CloudStorageAccount.Parse(_azureBlobSettings.BlobStorageConnectionString);

        //instantiate the client
        BlobClient = StorageAccount.CreateCloudBlobClient();

        //set the container
        Container = BlobClient.GetContainerReference(_azureBlobSettings.ContainerBlobAzureId);
    }

    public CloudStorageAccount StorageAccount { get; private set; }
    public CloudBlobClient BlobClient { get; private set; }
    public CloudBlobContainer Container { get; private set; }
}

And registered as a singleton with the service collection

public void ConfigureServices(IServiceCollection services) {

    //...

    service.AddSingleton<IAzureFileStorage, AzureFileStorage>();

    //...
}

So that where ever IAzureFileStorage is explicitly injected,

private readonly IAzureFileStorage fileStore;

public SomeClass(IAzureFileStorage fileStore) {
    this.fileStore = fileStore;
}

the same instance will be used through out the application.