在 SimpleInjector 中注册多个 AmazonS3Clients 并配置 Adapter

Registering multiple AmazonS3Clients in SimpleInjector and configuring Adapter

问题如下:

我必须访问 2 个不同的 S3 存储桶,我创建 AmazonS3 客户端的方式如下:

var client = new AmazonS3Client(accesKey,secretKey, bucketRegion);

因为我有 2 个客户,所以我最终遵循了“依赖注入原则、实践和模式”一书中的建议,特别是第 6 章中的建议,我最终没有使用抽象工厂,而是使用了适配器。

这里是感兴趣的代码:

static async Task Main(string[] args)
{
    var s3Clients = new Dictionary<S3ClientType, IAmAnS3ClientQueryor>
    {
        {
            S3ClientType.Discriminator1,
            new S3Queryor(apiKey1, secretKey1, bucketRegion))
        },
        {
            S3ClientType.Discriminator2,
            new S3Queryor(new AmazonS3Client(apiKey2, secretKey2, bucketRegion))
        },
    };
    IGetFileNames fileNamesGetter = new S3FileNamesGetter(s3Clients);
    var uidMappingFileNames = fileNamesGetter.GetAsync(S3ClientType.Discriminator2, bucketName);
}

public interface IGetFileNames
{
    IAsyncEnumerable<string> GetAsync(S3ClientType discriminator, string bucketName);
}

public class S3FileNamesGetter: IGetFileNames
{
    private readonly IDictionary<S3ClientType, IAmAnS3ClientQueryor> s3Clients;

    public S3FileNamesGetter(IDictionary<S3ClientType, IAmAnS3ClientQueryor> s3Clients)
    {
        this.s3Clients = s3Clients;
    }

    public IAsyncEnumerable<string> GetAsync(S3ClientType type, string bucketName)
    {
        return s3Clients[type].GetFileNames(bucketName, token);
    }
}

public interface IAmAnS3ClientQueryor
{
    IAsyncEnumerable<string> GetFileNames(string bucketName);
}

public class S3Queryor : IAmAnS3ClientQueryor
{
    private readonly IAmazonS3 s3Client;

    public S3Queryor(IAmazonS3 s3Client)
    {
        this.s3Client = s3Client;
    }

    public async IAsyncEnumerable<string> GetFileNames(string bucketName)
    {
        // Returns filenames from S3
    }
}

在我尝试使用 SimpleInjector 时,我有:

static async Task Main(string[] args)
{
    var container = new Container();

    Bootstrap.Start(container, bucketRegion);

    var fileNamesGetter = container.GetInstance<IGetFileNames>();
    var uidMappingFileNames =
    fileNamesGetter.GetAsync(S3ClientType.Discriminator2, bucketName);
}

internal class Bootstrap
{
    public static void Start(Container container, RegionEndpoint bucketRegion)
    {
        container.Register<S3FileNamesGetter>();
        container.Options.EnableAutoVerification = false;

        var client1 = new AmazonS3Client( apiKey1, secretKey1, bucketRegion);
        var client2 = new AmazonS3Client( apiKey2, secretKey2, bucketRegion);

        var s3ClientsQueryors = new Dictionary<S3ClientType, IAmAnS3ClientQueryor>
        {
            {
                S3ClientType.Discriminator1, new S3Queryor(client1)
            },
            {
                S3ClientType.Discriminator2, new S3Queryor(client2)
            }
        };

        container.Collection.Register<IAmazonS3>(client1, client2);

        container.RegisterInstance<IDictionary<S3ClientType, IAmAnS3ClientQueryor>>(s3ClientsQueryors);

        container.RegisterInstance<IGetFileNames>(new S3FileNamesGetter(s3ClientsQueryors));
        container.Register<IAmAnS3ClientQueryor, S3Queryor>();
        container.Verify();
    }
}

但是当我 运行 这段代码时,我很正确地得到:

Unhandled exception. System.InvalidOperationException: The configuration is invalid. Creating the instance for type IAmAnS3ClientQueryor failed. The constructor of type S3Queryor contains the parameter with name 's3Client' and type IAmazonS3, bu t IAmazonS3 is not registered. For IAmazonS3 to be resolved, it must be registered in the container. There is, however, a registration for a collection of IAmazonS3 instances; Did you mean to depend on IEnumerable<IAmazonS3> instead? If you mean t to depend on IAmazonS3, you should use one of the Container.Register overloads instead of using Container.Collection.Register. Please see https://simpleinjector.org/collections for more information about registering and resolving collections. --->

信息很清楚。但是,第一个实例的问题是我有 2 个 S3 客户端,我希望最终将它们注入 S3Queryor.

所以问题是如何在简单注入器中注册我的依赖项以使用适配器模式。

=== 在@Steven 第一条评论后编辑。

我已经在此处创建了上面代码的回购 https://github.com/DavidSSL/SI-Trial

这是感谢@Steven 的方法:

internal static class Bootstrap
{
    public static void Start(Container container, RegionEndpoint bucketRegion)
    {
        container.RegisterInstance<IGetFileNames>(new S3FileNamesGetter(
            new Dictionary<S3ClientType, IAmAnS3ClientQueryor>
            {
                {
                    S3ClientType.Discriminator1,
                    new S3Queryor(new AmazonS3Client("apiKey1", "secretKey1", bucketRegion))
                },
                {
                    S3ClientType.Discriminator2,
                    new S3Queryor(new AmazonS3Client("apiKey2", "secretKey2", bucketRegion))
                },
            }));

        container.Options.EnableAutoVerification = false;

        container.Verify();
    }
}