Pin*_*tel 1 .net dependency-injection .net-core
我有和 类I1,其中继承( :)并在 中实现。我想注册一个作用域依赖项,以便在单个作用域内引用任何接口时始终返回相同的对象。I2FooI2I1I2I1I2FooFoo
我使用以下注册进行了尝试,但它Foo在同一范围内产生了三个不同的实例:
services.AddScoped<Foo>();
services.AddScoped<I1, Foo>();
services.AddScoped<I2, Foo>();
Run Code Online (Sandbox Code Playgroud)
我的定义如下:
interface I1
{
GetData();
}
interface I2 : I1
{
string Data { set; }
}
class Foo : I2
{
private string myData;
public string Data { set => myData = value; }
public string GetData() => this.myData;
}
Run Code Online (Sandbox Code Playgroud)
功能性使用。
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();
}
Run Code Online (Sandbox Code Playgroud)
GetData()from会返回在相同范围内AnotherBar设置在 Bar- 的相同数据吗?SetData()
这是使用 MS.DI 时需要注意的常见陷阱。这个陷阱被称为“撕裂的生活方式”。对于 MS.DI,每个注册都有自己的缓存。这意味着您的三个注册:
services.AddScoped<Foo>();
services.AddScoped<I1, Foo>();
services.AddScoped<I2, Foo>();
Run Code Online (Sandbox Code Playgroud)
每个都有自己的缓存和实例。这意味着以下断言成立:
using (var scope = provider.CreateScope())
{
Assert.AreSame(scope.GetService<I1>(), scope.GetService<I1>());
Assert.AreSame(scope.GetService<I2>(), scope.GetService<I2>());
Assert.AreNotSame(scope.GetService<I1>(), scope.GetService<I2>());
}
Run Code Online (Sandbox Code Playgroud)
要解决此问题,您必须将注册重写为以下内容:
services.AddScoped<Foo>();
services.AddScoped<I1>(c => c.GetRequiredService<Foo>());
services.AddScoped<I2>(c => c.GetRequiredService<Foo>());
Run Code Online (Sandbox Code Playgroud)
在这种情况下,每个注册仍然有自己的缓存,但由于第二个和第三个注册请求原始Foo服务,这确保所有三个注册在单个范围内返回相同的实例。
| 归档时间: |
|
| 查看次数: |
1250 次 |
| 最近记录: |