gpt4 book ai didi

c# - 作用域/ transient 依赖注入(inject)确保返回相同的接口(interface)和实现实例

转载 作者:行者123 更新时间:2023-12-04 12:11:10 25 4
gpt4 key购买 nike

请随意为这个问题提出一个更好的标题。我想不出一个好名字来描述这个问题。

我需要在启动时通过依赖注入(inject)来访问一个类。该类不仅应该通过它的具体实现可用,而且还应该通过它实现的接口(interface)可用。而且我需要确保它是通过两次注入(inject)返回的相同对象实例。

导致我进入单例案例的真实世界场景是提供接口(interface) (IStore) 的抽象 nuget,持有具体实现的多个 nuget(DBStore、RedisStore)。当我尝试为每个商店实现实现健康检查时,我可以注入(inject) IStore,但不能注入(inject)具体的实现。我想使用一些在具体实现中初始化和修改的变量(这就是为什么我需要两个注入(inject)相同的实例)。由于商店(希望)用作单例,因此它起作用了。我并不是说作用域和 transient 方式存在真实世界的场景。我只是好奇,如果他们不是单例,那是否可行。

以下代码描述了我如何使用单例做到这一点。

引导我使用单例解决方案的方式:

有这个界面:

public interface ITestInterface
{
string ReturnAString();
int ReturnAnInt();
}

而这个具体的实现
public class TestImplementation : ITestInterface
{
private int counter = 0;
public string ReturnAString() {return "a string"; }
public int ReturnAnInt() { return counter++; }
}

它们用于两个(假设)服务。一个要在构造函数中注入(inject)接口(interface),另一个需要具体的实现。

Startup.ConfigureServices 方法中的试验和错误,用于在两种情况下注入(inject)相同的实例:

尝试 1:
// only ITestInterface is injected but not TestImplemenation
services.AddSingleton<ITestInterface, TestImplementation>();

尝试2:
//only TestImplementation is injected (DI does not recognize it implements the Interface)
services.AddSingleton<TestImplementation>();

尝试3:
// both are injected but they are not singleton any more (counters increment independently)
services.AddSingleton<ITestInterface, TestImplementation>();
services.AddSingleton<TestImplementation, TestImplementation>();

尝试4:
TestImplementation instance = new TestImplementation();
services.AddSingleton<ITestInterface>(instance);
services.AddSingleton(instance);
//services.AddSingleton<TestImplementation>(instance);

好吧,在尝试 4 时,我有两个注入(inject)的相同实例。

现在让我们假设 TestImplementation 需要注入(inject)一些(例如连接)设置。

我可以编写一个扩展方法来从配置中获取设置并将其传递给单例实例。
TestImplementation instance = new TestImplementation(Configuration.GetTestSettings());
services.AddSingleton<ITestInterface>(instance);
services.AddSingleton(instance);

那么我将如何使用具有作用域或 transient 的相同设置来实现两次注入(inject)都是同一个实例?因为我认为我无法在那里手动/代码创建实例。

最佳答案

基本上,您想将单个服务实现类型注册为两个服务契约(具体类 + 接口(interface))。这是很常见的情况,但不幸的是,默认的 Microsoft DI 容器(ServiceCollection)的功能有限,我认为实现预期效果的唯一方法是使用工厂委托(delegate):

services.AddScoped<TestImplementation>();
services.AddScoped<ITestInterface>(s => s.GetRequiredService<TestImplementation>());

虽然这可以解决问题(需要一些额外的运行时成本),但我强烈建议使用功能齐全的 DI 容器之一,例如 Autofac 或 Ninject

关于c# - 作用域/ transient 依赖注入(inject)确保返回相同的接口(interface)和实现实例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54921823/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com