如何创建Singleton到依赖项注入Azure存储客户端和容器
问题描述:
我有一个类有一个方法来执行Azure存储的事情,目前我每次调用时创建StorageContainer,BlobClient和Container:如何创建Singleton到依赖项注入Azure存储客户端和容器
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
}
现在,我想将SaveImageBlob.ExecuteAsync方法和依赖注入到类中,以便将Azure存储项仅实例化一次。
我目前拥有的接口,例如:
namespace Domain.Interfaces
{
public interface IAzureStorage
{
CloudStorageAccount StorageAccount { get; }
CloudBlobClient BlobClient { get; }
CloudBlobContainer Container { get; }
}
}
而现在,我无能,如何实现该接口。
一旦接口被实现,我想我要改变SaveImageBlob.ExecuteAsync方法是:
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
}
我只需要知道如何实现,这将让我的DI接口将AzureStorage类作为Singleton传入SaveImageBlob。这并不重要,但为了后代的缘故,我使用了Autofac for DI。
答
一个单身的基本思路是由私人静态实例变量和一个公共静态实例属性是线程安全检查是否设置了实例变量,如果不是,则设置它,然后返回它。
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;
}
}
}
本练习留给读者的是提供配置。
答
我在我的项目中有类似的要求。
我的工作方式是创建一个StorageTableProviderFactory
......这个工厂只会在启动时创建,但会为DI容器提供所需的引用。工厂将返回一个对象IStorageTableProvider
,该对象现在可以根据需要注入。
==============
var StorageTableProviderOptions = new Core.StorageTableProviderProvider.Options()
{
Mode = DataSettings.StorageTableProviderProvider_mode,
StorageTable_ConnectionString = DataSettings.StorageTableProvider_StorageTable_ConnectionString
};
container.Register(() => StorageTableProviderFactory.CreateNew(StorageTableProviderOptions));