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
实例,但它们的设置凭据不同:
在myStartup.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