I have a class that has a method that does Azure Storage things and currently, I am creating the StorageContainer, BlobClient, and Container every single time it is called:
private readonly IAzureStorageConfig _config;
public SaveImageBlob(IAzureStorageConfig config)
{
_config = config;
}
public async Task<T> ExecuteAsync(ImageSaveInput input)
{
//get the storage account from the connection string
CloudStorageAccount storageAccount = CloudStorageAccount.Parse(_config.ConnectionString);
//instantiate the client
CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();
//set the container
CloudBlobContainer container = blobClient.GetContainerReference(_config.ImagesContainerName);
//... do things and stuff
}
Now, I want to rip that out of the SaveImageBlob.ExecuteAsync method and dependency inject it into the class, so the Azure Storage items are instantiated only once.
I currently have the interface as such:
namespace Domain.Interfaces
{
public interface IAzureStorage
{
CloudStorageAccount StorageAccount { get; }
CloudBlobClient BlobClient { get; }
CloudBlobContainer Container { get; }
}
}
And now, I am clueless as to how to implement that interface.
Once the interface is implemented, I imagine I'm going to change the SaveImageBlob.ExecuteAsync method to this:
private readonly IAzureStorageConfig _config;
private readonly IAzureStorage _storage;
public SaveImageBlob(IAzureStorageConfig config,
IAzureStorage storage)
{
_config = config;
_storage = storage;
}
public async Task<T> ExecuteAsync(ImageSaveInput input)
{
//now, since I don't have to create an instance of the storageAccount, blobClient, and container, I can just access them from _storage
//create the blockBlob
CloudBlockBlob blockBlob = _storage.Container.GetBlockBlobReference(input.BlobUrl);
//... do things and stuff with a Stream (doesn't really matter)
//upload the blob
blockBlob.UploadFromStreamAsync(stream);
//do more things and stuff and return something
}
I just need to know how to implement the interface that will allow me to DI the AzureStorage class into SaveImageBlob as a Singleton. Not that it matters, but for posterity sake, I'm using Autofac for DI.
The basic idea of a singleton consists of a private static instance variable and a public static Instance property that thread-safely checks if the instance variable is set, sets it if it isn't, then returns it.
using Microsoft.WindowsAzure.Storage;
using Microsoft.WindowsAzure.Storage.Blob;
using System;
public sealed class AzureStorage
{
private static volatile AzureStorage instance;
private static object syncRoot = new Object();
public CloudStorageAccount StorageAccount { get; private set; }
public CloudBlobClient BlobClient { get; private set; }
public CloudBlobContainer Container { get; private set; }
private AzureStorage()
{
StorageAccount = CloudStorageAccount.Parse(_config.ConnectionString);
//instantiate the client
BlobClient = StorageAccount.CreateCloudBlobClient();
//set the container
Container = BlobClient.GetContainerReference(_config.ImagesContainerName);
}
public static AzureStorage Instance
{
get
{
if (instance == null)
{
lock (syncRoot)
{
if (instance == null)
instance = new AzureStorage();
}
}
return instance;
}
}
}
The exercise left to the reader is to provide the configuration.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With