gpt4 book ai didi

c# - 同一存储的依赖注入(inject)多个接口(interface)(具有不同的connectionString)

转载 作者:行者123 更新时间:2023-12-04 07:22:28 24 4
gpt4 key购买 nike

我想在 Startup.cs 中添加两个或更多(取决于我想添加到我的应用程序的 azure 存储容器的数量)服务
我的 appsettings.json:

"AzureBlobStorageConfiguration": {
"Storages": {
"Storage1": {
"StorageName": "Storage1",
"ConnString": "connString",
"AzureBlobContainerName": "containerName"
},
"Storage2": {
"StorageName": "Storage2",
"ConnString": "connString",
"AzureBlobContainerName": "containerName"
},
"Storage3": {
"StorageName": "Storage3",
"ConnString": "connString",
"AzureBlobContainerName": "containerName"
}
}
接下来在 Startup.cs 中使用方法添加服务:
 public static IServiceCollection AddAzureStorage1(this IServiceCollection services, IConfiguration configuration)
{
var options = new ABlobStorageConfigurationOptionsDTO();
configuration.GetSection("AzureBlobStorageConfiguration").GetSection("Storages").GetSection("Storage1").Bind(options);

services.AddTransient<IAzureBlobStorage1, AzureBlobStorage1>(isp =>
{
var client = new BlobServiceClient(options.ConnString);
var container = client.GetBlobContainerClient(options.AzureBlobContainerName);
var containerName = options.AzureBlobContainerName;
var storageName = options.StorageName;

return new AzureBlobStorage1(container, containerName, storageName);
}
);
return services;
}
我的 IAzureBlobStorage1 看起来像:
public interface IAzureBlobStorage1
{
string AzureBlobContainerName { get; }
string StorageName { get; }

public Task<Stream> DownloadStreamAsyns(string fileName);

public Task Upload(string fileId, Stream stream);

}
和 AzureBlobStorage1 :
    public class AzureBlobStorage1 : IAzureBlobStorage1
{
private BlobContainerClient _client;
private string _containerName;
private string _storageName;
public string StorageName => _storageName;
public string AzureBlobContainerName => _containerName;

public AzureBlobStorage1(BlobContainerClient client, string containerName, string storageName)
{
_client = client;
_containerName = containerName;
_storageName = storageName;
}


public async Task<Stream> DownloadStreamAsyns(string fileName)
{
return await _client.GetBlobClient(fileName).OpenReadAsync();
}

public async Task Upload(string fileId, Stream stream)
{
await _client.GetBlobClient(fileId).UploadAsync(stream);
}
}
在此之后,我可以在我的构造函数 Controller 类中注入(inject)接口(interface):
        public Controller(IAzureBlobStorage1 azureStorage)
{
_azureStorage1 = azureStorage;

}
但是,如果我想添加许多存储(我在 appsetings.json 中有 3 个),我必须:
  • 创建接口(interface) IAzureBlobStorage2(看起来与 IAzureBlobStorage1 相同 - 仅更改名称)
  • 创建类 AzureBlobStorage2(看起来像 AzureBlobStorage1 - 只是名称更改)
  • 更改类名的复制粘贴方法
  • public static IServiceCollection AddAzureStorage2(this IServiceCollection services, IConfiguration configuration)
    {
    var options = new ABlobStorageConfigurationOptionsDTO();
    configuration.GetSection("AzureBlobStorageConfiguration").GetSection("Storages").GetSection("Storage2").Bind(options);

    services.AddTransient<IAzureBlobStorage2, AzureBlobStorage2>(isp =>
    {
    var client = new BlobServiceClient(options.ConnString);
    var container = client.GetBlobContainerClient(options.AzureBlobContainerName);
    var containerName = options.AzureBlobContainerName;
    var storageName = options.StorageName;

    return new AzureBlobStorage2(container, containerName, storageName);
    }
    );
    return services;
    }
    现在我可以通过
      public Controller(IAzureBlobStorage2 azureStorage)
    {
    _azureStorage2 = azureStorage;

    }
    如果我想添加我的第三个存储,我需要第三次复制粘贴我的代码。
    对我来说,这个解决方案看起来很糟糕,我在想如何解决它并使我的代码干净。

    最佳答案

    不确定这是否是最佳实践,但您可以设计一个命名服务提供商,也许吧?要么,或者你可以只是一个通用参数来区分它们,但是这个通用参数除了作为一种区分方式之外没有多大意义。
    无论如何,这是一个使用某种命名提供者的非常基本的实现?:

    public interface INamedService {
    string Identifier { get; }
    }

    public interface IAzureBlobStorage : INamedService
    {
    string AzureBlobContainerName { get; }
    string StorageName { get; }
    Task<Stream> DownloadStreamAsyns(string fileName);
    Task Upload(string fileId, Stream stream);
    }

    public class NamedServiceProvider<T>
    where T : INamedService
    {
    readonly IReadOnlyDictionary<string, T> Instances;

    public NamedServiceProvider(
    IEnumerable<T> instances)
    {
    Instances = instances?.ToDictionary(x => x.Identifier) ??
    throw new ArgumentNullException(nameof(instances));
    }

    public bool TryGetInstance(string identifier, out T instance) {
    return Instances.TryGetValue(identifier, out instance);
    }
    }

    public class AzureBlobStorage : IAzureBlobStorage
    {
    public string Identifier { get; }
    private BlobContainerClient _client;
    private string _containerName;
    private string _storageName;
    public string StorageName => _storageName;
    public string AzureBlobContainerName => _containerName;

    public AzureBlobStorage(string identifier, BlobContainerClient client, string containerName, string storageName)
    {
    Identifier = identifier;
    _client = client;
    _containerName = containerName;
    _storageName = storageName;
    }


    public async Task<Stream> DownloadStreamAsyns(string fileName)
    {
    return await _client.GetBlobClient(fileName).OpenReadAsync();
    }

    public async Task Upload(string fileId, Stream stream)
    {
    await _client.GetBlobClient(fileId).UploadAsync(stream);
    }
    }
    然后是静态扩展方法:
    public static IServiceCollection AddAzureStorage(
    this IServiceCollection services,
    IConfiguration configuration,
    string identifier)
    {
    var options = new ABlobStorageConfigurationOptionsDTO();
    configuration
    .GetSection("AzureBlobStorageConfiguration")
    .GetSection("Storages")
    .GetSection(identifier)
    .Bind(options);

    return services
    .TryAddTransient<NamedServiceProvider<IAzureBlobStorage>>()
    .AddTransient<IAzureBlobStorage, AzureBlobStorage>(isp =>
    {
    var client = new BlobServiceClient(options.ConnString);
    var container = client.GetBlobContainerClient(options.AzureBlobContainerName);
    var containerName = options.AzureBlobContainerName;
    var storageName = options.StorageName;

    return new AzureBlobStorage(identifier, container, containerName, storageName);
    });
    }
    然后你可以像这样调用使用它:
    public Controller(NamedServiceProvider<IAzureBlobStorage> azureStorage)
    {
    _ = azureStorage ?? throw new ArgumentNullException(nameof(azureStorage));
    _azureStorage2 = azureStorage.TryGetInstance("Storage2", out var instance) ? instance : throw new Exception("Something about the identifier not being found??");
    }
    我在智能感知环境之外对此进行了编码,如果有任何较小的拼写错误或错误,请见谅。可能有更好的方法来做到这一点,但这似乎至少有点ok-ish?哦,我只改变了我必须做的事情,以使其能够正常工作。我不想触及任何其他逻辑..

    关于c# - 同一存储的依赖注入(inject)多个接口(interface)(具有不同的connectionString),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68414405/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com