C# 将多个实现注册到同一接口

C# 将多个实现注册到同一接口,c#,dependency-injection,.net-core,asp.net-core-webapi,C#,Dependency Injection,.net Core,Asp.net Core Webapi,我有一个blobstoragepository类,用于与Azure blob存储交互。它实现了一个接口IBlobStorageRepository 我需要使用两个blobstoragepositional实例,但它们的设置凭据不同: 在myStartup.cs中: // Normal storage var storageCredentials = new StorageCredentials(_appSettings.BlobStorageAccountName, _appSettings.B

我有一个
blobstoragepository
类,用于与Azure blob存储交互。它实现了一个接口
IBlobStorageRepository

我需要使用两个
blobstoragepositional
实例,但它们的设置凭据不同:

在my
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);
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;
}

编辑:我的问题不是的重复,因为我想在添加服务时传递实例化的类,即
services.AddSingleton(blobRepository)
,而您无法将实例化的类传递给
serviceProvider.GetService()
,不幸的是,我找不到“命名实例”嵌入式ASP.NET核心DI容器中的功能。在你可以使用的地方

在您的情况下,您可以这样做:

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];
    }
}
public enum RepoTypes{Blob,检疫}
...
公共接口IRepoResolver
{
//解析使用方法
IBlobStorageRepository GetRepo(报告类型);
//解析usnig索引器
IBlobStorageRepository此[RepoTypes rt]{get;}
}
...
公共解析程序:IRepoResolver
{
私人只读词典;
公共重新解析程序()
{
_repos[RepoTypes.Blob]=新的BlobStorageRepository(…);
_repos[RepoTypes.quantial]=新的BlobStorageRepository(…);
}
public IBlobStorageRepository GetRepo(RepoTypes rt)=>\u repos[rt];
public IBlobStorageRepository this[RepoTypes rt]{get=>\u repos[rt];}
}
...
services.AddSingleton();
...
公开课
{
公共部分(IRER)
{
var blob1=rr.GetRepo(RepoTypes.Blob);
var blob2=rr[RepoTypes.Blob];
}
}

不幸的是,我在嵌入式ASP.NET核心DI容器中找不到“命名实例”功能。在你可以使用的地方

在您的情况下,您可以这样做:

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];
    }
}
public enum RepoTypes{Blob,检疫}
...
公共接口IRepoResolver
{
//解析使用方法
IBlobStorageRepository GetRepo(报告类型);
//解析usnig索引器
IBlobStorageRepository此[RepoTypes rt]{get;}
}
...
公共解析程序:IRepoResolver
{
私人只读词典;
公共重新解析程序()
{
_repos[RepoTypes.Blob]=新的BlobStorageRepository(…);
_repos[RepoTypes.quantial]=新的BlobStorageRepository(…);
}
public IBlobStorageRepository GetRepo(RepoTypes rt)=>\u repos[rt];
public IBlobStorageRepository this[RepoTypes rt]{get=>\u repos[rt];}
}
...
services.AddSingleton();
...
公开课
{
公共部分(IRER)
{
var blob1=rr.GetRepo(RepoTypes.Blob);
var blob2=rr[RepoTypes.Blob];
}
}

开箱即用,您所能做的就是使用以下方法注入接口的所有实例:

public MyClass(List<IBlobStorageRepository> repos)
公共MyClass(列表回购)
然后,您需要自己决定如何从列表中为要设置的每个ivar提取正确的实例

在这种情况下,通常最好创建一个工厂类并将其注入。例如,您可以拥有一个
blobstoragepositoryfactory
,并提供一种方法来为您需要的特定场景返回存储库实例。这可能是一种方法、属性等,由您决定。关键是,工厂协调管理存储库和提供API以检索正确存储库的逻辑


或者,您可以使用更健壮的DI容器来补充
Microsoft.Extensions.DependencyInjection
。支持的容器列表可在以下位置找到:。

开箱即用,您所能做的就是使用以下命令注入接口的所有实例:

public MyClass(List<IBlobStorageRepository> repos)
公共MyClass(列表回购)
然后,您需要自己决定如何从列表中为要设置的每个ivar提取正确的实例

在这种情况下,通常最好创建一个工厂类并将其注入。例如,您可以拥有一个
blobstoragepositoryfactory
,并提供一种方法来为您需要的特定场景返回存储库实例。这可能是一种方法、属性等,由您决定。关键是,工厂协调管理存储库和提供API以检索正确存储库的逻辑


或者,您可以使用更健壮的DI容器来补充
Microsoft.Extensions.DependencyInjection
。支持的容器列表可在以下位置找到:。

以供将来参考-我结合使用mtkachenko和Chris Pratt的答案解决此问题的方法:

创建了一个
blobstoragepositoryfactory

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];
    }
}
最后,在我的服务中:

private readonly IBlobStorageRepository _blobStorageRepository;
private readonly IBlobStorageRepository _quarantineBlobStorageRepository;

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

供将来参考-我结合mtkachenko和Chris Pratt的答案解决了这个问题:

创建了一个
blobstoragepositoryfactory

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];
    }
}
最后,在我的服务中:

private readonly IBlobStorageRepository _blobStorageRepository;
private readonly IBlobStorageRepository _quarantineBlobStorageRepository;

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

@PavelAnikhouski的可能重复项这不是重复项。用例是不同的。@chris的想法是相同的。您应该将所有实现注册为self+factory,以按名称获取实例,然后注入factory而不是接口:
\u blobstorageposition=repoFactory.get(RepoType.Blob)@mtkachenko如何按名称获取实例?如果可能的话,最好是一个代码示例。可能是@PavelAnikhouski的重复。这不是重复。用例是不同的。@chris的想法是相同的。您应该将所有实现注册为self+factory,以按名称获取实例,然后注入factory而不是接口:
\u blobstorageposition=repoFactory.get(RepoType.Blob)@mtkachenko如何按名称获取实例?如果可能的话,一个代码示例会很棒。非常感谢。我的实现略有不同,但原则是一样的。非常感谢。虽然实现方法略有不同,但原理相同。使用
void Register(…)
方法是个坏主意。您在
Bl中使用
Dictionary