Зарегистрируйте несколько реализаций в одном интерфейсе - PullRequest
0 голосов
/ 10 июля 2019

У меня есть класс BlobStorageRepository, который используется для взаимодействия с хранилищем BLOB-объектов Azure. Реализует интерфейс IBlobStorageRepository.

Мне нужно использовать два экземпляра BlobStorageRepository, но они настроены с разными учетными данными:

По моему Startup.cs:

// Normal storage
var storageCredentials = new StorageCredentials(_appSettings.BlobStorageAccountName, _appSettings.BlobStorageAccountKey);
var cloudBlobStorageAccount = new CloudStorageAccount(storageCredentials, true);
var cloudBlobClient = cloudBlobStorageAccount.CreateCloudBlobClient();
var blobRepository = new BlobStorageRepository(cloudBlobClient);

// Quarantine storage
var quarantineStorageCredentials = new StorageCredentials(_appSettings.QuarantineBlobStorageAccountName, _appSettings.QuarantineBlobStorageAccountKey);
var quarantineCloudBlobStorageAccount = new CloudStorageAccount(quarantineStorageCredentials, true);
var quarantineCloudBlobClient = quarantineCloudBlobStorageAccount.CreateCloudBlobClient();
var quarantineBlobRepository = new BlobStorageRepository(quarantineCloudBlobClient);

services.AddSingleton<IBlobStorageRepository>(blobRepository);
services.AddSingleton<IBlobStorageRepository>(quarantineBlobRepository);

Как я могу настроить вышеупомянутое, чтобы я мог разрешить зависимости в моем классе и получить два разных экземпляра, т.е.:

private readonly IBlobStorageRepository _blobStorageRepository;
private readonly IBlobStorageRepository _quarantineBlobStorageRepository;

public DocumentService(IBlobStorageRepository blobStorageRepository, IBlobStorageRepository quarantineBlobStorageRepository)
{
    _blobStorageRepository = blobStorageRepository;
    _quarantineBlobStorageRepository = quarantineBlobStorageRepository;
}

Редактировать : Мой вопрос не является дубликатом Как зарегистрировать несколько реализаций одного и того же интерфейса в Asp.Net Core? , потому что я хочу передать экземпляр класса при добавлении сервис, т.е. services.AddSingleton<IBlobStorageRepository>(blobRepository), и вы не можете передать экземпляр класса serviceProvider.GetService<BlobStorageRepository>().

Ответы [ 3 ]

1 голос
/ 10 июля 2019

Из коробки все, что вы можете сделать, это ввести все экземпляры интерфейса, используя:

public MyClass(List<IBlobStorageRepository> repos)

Затем вам нужно решить для себя, как вытащитьправый экземпляр из списка для каждого ивара, который вы хотите установить.

Обычно в этом типе сценария лучше создать фабричный класс и внедрить его вместо этого.Например, вы можете иметь BlobStorageRepositoryFactory и предоставить способ вернуть экземпляр репозитория для конкретного сценария, который вам требуется.Это может быть метод, свойство и т. Д. Это зависит от вас.Дело в том, что фабрика координирует логику как для управления репозиториями, так и для предоставления API для получения нужного.

В качестве альтернативы, вы можете дополнить Microsoft.Extensions.DependencyInjection более надежным DI-контейнером.Список поддерживаемых контейнеров можно найти по адресу: https://github.com/aspnet/Extensions/tree/master/src/DependencyInjection.

1 голос
/ 10 июля 2019

К сожалению, я не могу найти функциональность "именованных экземпляров" во встроенном контейнере ASP.NET Core DI.В Autofac вы можете использовать Именованные и ключевые службы .

В вашем случае вы можете сделать что-то вроде этого:

public enum RepoTypes { Blob, Quarantine }

...

public interface IRepoResolver
{
    //resolve using method
    IBlobStorageRepository GetRepo(RepoTypes rt);

    //resolve usnig indexer
    IBlobStorageRepository this[RepoTypes rt] { get; }
}

...

public sealed RepoResolver : IRepoResolver
{
    private readonly Dictionary<RepoTypes, IBlobStorageRepository> _repos;

    public RepoResolver()
    {
        _repos[RepoTypes.Blob] = new BlobStorageRepository(...);
        _repos[RepoTypes.Quarantine] = new BlobStorageRepository(...);
    }

    public IBlobStorageRepository GetRepo(RepoTypes rt) => _repos[rt];

    public IBlobStorageRepository this[RepoTypes rt] { get => _repos[rt]; }
}

...

services.AddSingleton<IRepoResolver, RepoResolver>();

...

public class Some
{
    public Some(IRepoResolver rr)
    {
        var blob1 = rr.GetRepo(RepoTypes.Blob);
        var blob2 = rr[RepoTypes.Blob];
    }
}
0 голосов
/ 10 июля 2019

Для дальнейшего использования - способ, которым я решил это, используя комбинацию ответов mtkachenko и Криса Пратта:

Создано BlobStorageRepositoryFactory:

public enum BlobStorageRepositoryType
{
    Core,
    Quarantine
}

public interface IBlobStorageRepositoryFactory
{
    void Register(BlobStorageRepositoryType type, IBlobStorageRepository blobRepository);
    IBlobStorageRepository Resolve(BlobStorageRepositoryType type);
}

public class BlobStorageRepositoryFactory : IBlobStorageRepositoryFactory
{
    private readonly Dictionary<BlobStorageRepositoryType, IBlobStorageRepository> _blobRepositories = new Dictionary<BlobStorageRepositoryType, IBlobStorageRepository>();

    public void Register(BlobStorageRepositoryType type, IBlobStorageRepository blobRepository)
    {
        _blobRepositories[type] = blobRepository;
    }

    public IBlobStorageRepository Resolve(BlobStorageRepositoryType type)
    {
        return _blobRepositories[type];
    }
}

Тогда в моем Startup.cs:

var blobStorageRepositoryFactory = new BlobStorageRepositoryFactory();
blobStorageRepositoryFactory.Register(BlobStorageRepositoryType.Core, GetBlobStorageRepository(_appSettings.BlobStorageAccountName, _appSettings.BlobStorageAccountKey));
blobStorageRepositoryFactory.Register(BlobStorageRepositoryType.Quarantine, GetBlobStorageRepository(_appSettings.QuarantineBlobStorageAccountName, _appSettings.QuarantineBlobStorageAccountKey));
services.AddSingleton<IBlobStorageRepositoryFactory>(blobStorageRepositoryFactory);

private static BlobStorageRepository GetBlobStorageRepository(string accountName, string accountKey)
{
    var storageCredentials = new StorageCredentials(accountName, accountKey);
    var cloudBlobStorageAccount = new CloudStorageAccount(storageCredentials, true);
    var cloudBlobClient = cloudBlobStorageAccount.CreateCloudBlobClient();
    var blobRepository = new BlobStorageRepository(cloudBlobClient);
    return blobRepository;
}

И, наконец, в моем распоряжении:

private readonly IBlobStorageRepository _blobStorageRepository;
private readonly IBlobStorageRepository _quarantineBlobStorageRepository;

public DocumentService(IBlobStorageRepositoryFactory blobStorageRepositoryFactory)
{
    _blobStorageRepository = blobStorageRepositoryFactory.Resolve(BlobStorageRepositoryType.Core);
    _quarantineBlobStorageRepository = blobStorageRepositoryFactory.Resolve(BlobStorageRepositoryType.Quarantine);
}
...