具有继承接口的.NET核心依赖项注入

具有继承接口的.NET核心依赖项注入,.net,.net-core,dependency-injection,.net,.net Core,Dependency Injection,我有I1,I2和类Foo,其中I2继承I1(I2:I1)并且I2在Foo中实现。我想注册一个作用域依赖项,这样当在单个作用域中引用任何接口时,它总是返回相同的Foo对象 我尝试使用以下注册,但它在同一范围内产生了三个不同的Foo实例: services.AddScoped<Foo>(); services.AddScoped<I1, Foo>(); services.AddScoped<I2, Foo>(); 功能性使用。 class Bar { p

我有
I1
I2
和类
Foo
,其中
I2
继承
I1
I2
I1
)并且
I2
Foo
中实现。我想注册一个作用域依赖项,这样当在单个作用域中引用任何接口时,它总是返回相同的
Foo
对象

我尝试使用以下注册,但它在同一范围内产生了三个不同的
Foo
实例:

services.AddScoped<Foo>();
services.AddScoped<I1, Foo>();
services.AddScoped<I2, Foo>();
功能性使用。

class Bar
{
    private I2 _i2;
    public Bar(I2 i2) => _i2 = i2;

    public void SetData() => _i2.myData = "My Data";
}

class AnotherBar
{
    private I1 _i1;
    public AnotherBar(I1 i1) => _i1 = i1;

    public string GetData() => _i1.GetData();
}

GetData()
从另一个Bar返回的数据与在同一范围内设置在Bar上的数据相同-
SetData()

这是使用MS.DI时需要注意的常见陷阱。陷阱被称为。对于MS.DI,每个注册都有自己的缓存。这意味着您的三次注册:

services.addScope();
services.addScope();
services.addScope();
每个都有自己的缓存和实例。这意味着以下断言成立:

使用(var scope=provider.CreateScope())
{
Assert.arame(scope.GetService(),scope.GetService());
Assert.arame(scope.GetService(),scope.GetService());
Assert.AreNotSame(scope.GetService(),scope.GetService());
}
要解决此问题,您必须将注册重写为以下内容:

services.addScope();
services.addScope(c=>c.GetRequiredService());
services.addScope(c=>c.GetRequiredService());

在这种情况下,每个注册仍然有自己的缓存,但是由于第二个和第三个请求原始
Foo
服务,这确保了所有三个注册在单个范围内返回相同的实例。

您正在注册
Foo
的三个独立实例。他们不会共享一个州。您可以使用
Foo
I1
I2
注入每一个。尝试将所有3个输入到
条中
,并查看它们的值。他们都会不同的。谢谢史蒂文,你分享的很好,我也分享了。非常感谢。
class Bar
{
    private I2 _i2;
    public Bar(I2 i2) => _i2 = i2;

    public void SetData() => _i2.myData = "My Data";
}

class AnotherBar
{
    private I1 _i1;
    public AnotherBar(I1 i1) => _i1 = i1;

    public string GetData() => _i1.GetData();
}