Ily*_*lya 18 c# dependency-injection asp.net-core
我如何为特定类注入不同的对象实现?
例如,在统一中我可以:定义两个实现 IRepository
container.RegisterType<IRepository, TestSuiteRepositor("TestSuiteRepository");
container.RegisterType<IRepository, BaseRepository>();
Run Code Online (Sandbox Code Playgroud)
并致电所需的实施
public BaselineManager([Dependency("TestSuiteRepository")]IRepository repository)
Run Code Online (Sandbox Code Playgroud)
ade*_*lin 21
正如@Tseng指出的那样,没有内置的命名绑定解决方案.但是,使用工厂方法可能对您的情况有所帮助.示例应如下所示:
创建存储库解析程序:
public interface IRepositoryResolver
{
IRepository GetRepositoryByName(string name);
}
public class RepositoryResolver : IRepositoryResolver
{
private readonly IServiceProvider _serviceProvider;
public RepositoryResolver(IServiceProvider serviceProvider)
{
_serviceProvider = serviceProvider;
}
public IRepository GetRepositoryByName(string name)
{
if(name == "TestSuiteRepository")
return _serviceProvider.GetService<TestSuiteRepositor>();
//... other condition
else
return _serviceProvider.GetService<BaseRepositor>();
}
}
Run Code Online (Sandbox Code Playgroud)
注册所需的服务 ConfigureServices.cs
services.AddSingleton<IRepositoryResolver, RepositoryResolver>();
services.AddTransient<TestSuiteRepository>();
services.AddTransient<BaseRepository>();
Run Code Online (Sandbox Code Playgroud)
最后在任何类中使用它:
public class BaselineManager
{
private readonly IRepository _repository;
public BaselineManager(IRepositoryResolver repositoryResolver)
{
_repository = repositoryResolver.GetRepositoryByName("TestSuiteRepository");
}
}
Run Code Online (Sandbox Code Playgroud)
nel*_*eus 19
除了@ adem-caglin回答之外,我还想在这里发布一些我为基于名称的注册创建的可重用代码.
更新现在它可以作为nuget包使用.
要注册您的服务,您需要在Startup课程中添加以下代码:
services.AddTransient<ServiceA>();
services.AddTransient<ServiceB>();
services.AddTransient<ServiceC>();
services.AddByName<IService>()
.Add<ServiceA>("key1")
.Add<ServiceB>("key2")
.Add<ServiceC>("key3")
.Build();
Run Code Online (Sandbox Code Playgroud)
然后你可以通过IServiceByNameFactory界面使用它:
public AccountController(IServiceByNameFactory<IService> factory) {
_service = factory.GetByName("key2");
}
Run Code Online (Sandbox Code Playgroud)
扩展的完整代码在github中.
Mus*_*tor 14
通过 .NET 8,我们获得了扩展库的更新,它带来了键控 DI 服务,因此现在有了一个内置解决方案。
这里引用了 Microsoft 文档:What's new in .NET 8? - 密钥 DI 服务:
键控依赖注入 (DI) 服务提供了一种使用密钥注册和检索 DI 服务的方法。通过使用密钥,您可以确定注册和使用服务的方式。以下是一些新的 API:
以下示例向您展示如何使用密钥 DI 服务。
using Microsoft.Extensions.Caching.Memory;
using Microsoft.Extensions.Options;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddSingleton<BigCacheConsumer>();
builder.Services.Addsingleton<SmallCacheConsumer>();
builder.Services.AddKeyedSingleton<IMemoryCache, BigCache>("big");
builder.Services.AddKeyedSingleton<IMemoryCache, SmallCache>("small");
var app = builder.Build();
app.MapGet("/big", (BigCacheConsumer data) => data.GetData());
app.MapGet("/small", (SmallCacheConsumer data) => data.GetData());
app.Run();
class BigCacheConsumer([FromKeyedServices("big")] IMemoryCache cache)
{
public object? GetData() => cache.Get("data");
}
class SmallCacheConsumer(IKeyedServiceProvider keyedServiceProvider)
{
public object? GetData() => keyedServiceProvider.GetRequiredKeyedService<IMemoryCache>("small");
}
Run Code Online (Sandbox Code Playgroud)
有关更多信息,请参阅dotnet/runtime#64427。
您不能使用内置的ASP.NET Core IoC容器。
这是设计使然。内置容器有意保持简单易扩展,因此,如果需要更多功能,可以插入第3方容器。
您必须使用第三方容器来执行此操作,例如Autofac(请参阅docs)。
public BaselineManager([WithKey("TestSuiteRepository")]IRepository repository)
Run Code Online (Sandbox Code Playgroud)
在阅读了依赖注入的官方文档后,我认为你不能用这种方式做到这一点。
但我的问题是:你是否同时需要这两个实现?因为如果不这样做,你可以通过环境变量创建多个环境,并根据当前环境在类中拥有特定的功能Startup,甚至创建多个Startup{EnvironmentName}类。
当 ASP.NET Core 应用程序启动时,该类
Startup用于引导应用程序、加载其配置设置等(了解有关 ASP.NET 启动的更多信息)。但是,如果存在一个已命名的类Startup{EnvironmentName}(例如StartupDevelopment),并且ASPNETCORE_ENVIRONMENT环境变量与该名称匹配,则将Startup使用该类。因此,您可以Startup针对开发进行配置,但有一个单独的组件StartupProduction,当应用程序在生产环境中运行时将使用该组件。或相反亦然。
我还写了一篇关于从 JSON 文件注入依赖项的文章,这样您就不必每次想要在实现之间切换时重新编译整个应用程序。基本上,您可以使用如下服务保留一个 JSON 数组:
"services": [
{
"serviceType": "ITest",
"implementationType": "Test",
"lifetime": "Transient"
}
]
Run Code Online (Sandbox Code Playgroud)
然后您可以在此文件中修改所需的实现,而不必重新编译或更改环境变量。
希望这可以帮助!
| 归档时间: |
|
| 查看次数: |
11545 次 |
| 最近记录: |