Nic*_*ler 3 c# dependency-injection asp.net-core
假设我有一个我想用scoped生命周期来解决的服务.但有时我尝试将其解析为接口类型,有时在实现类型.
我试图做的第一件事是:
ServiceCollection services;
services.AddScoped<MyClass>();
services.AddScoped<IMyInterface, MyClass>();
Run Code Online (Sandbox Code Playgroud)
上面的示例的问题是,如果我解析IMyInterface,则使用不同的实例,而不是解析MyClass.基本上,两个范围的实例可能同时存在.
我通过以下方式解决此问题.但它很容易出错,因为你很容易忘记在一个地方做这件事,而且很难注意到.
serviceCollection.AddScoped<MyClass>();
serviceCollection.AddScoped<IMyInterface, MyClass>(sp => sp.GetRequiredService<MyClass>());
Run Code Online (Sandbox Code Playgroud)
有没有办法以一种不易出错的方式完成我想要的东西.优先,但不一定,在一次注册?
即作为xUnit测试:
public class Tests
{
[Fact]
public void ReturnsSameInstanceForImplementationAndServiceType()
{
var serviceCollection = new ServiceCollection();
// TODO: Change these lines so they're less error prone.
serviceCollection.AddScoped<MyClass>();
serviceCollection.AddScoped<IMyInterface, MyClass>(sp => sp.GetRequiredService<MyClass>());
var services = serviceCollection.BuildServiceProvider();
var myInt = services.GetRequiredService<IMyInterface>();
var myCls = services.GetRequiredService<MyClass>();
Assert.Equal(myCls, myInt);
}
class MyClass : IMyInterface { }
interface IMyInterface { }
}
Run Code Online (Sandbox Code Playgroud)
一种选择是创建自己的扩展方法,将您在问题中显示的两条线包装起来.例如:
public static class ServiceCollectionExtensions
{
public static void AddScopedInterfaceAndClass<TInterface, TClass>(this IServiceCollection serviceCollection)
where TInterface : class
where TClass : class, TInterface
{
serviceCollection.AddScoped<TClass>();
serviceCollection.AddScoped<TInterface, TClass>(sp => sp.GetRequiredService<TClass>());
}
}
Run Code Online (Sandbox Code Playgroud)
你可以这样称呼它:
serviceCollection.AddScopedInterfaceAndClass<IMyInterface, MyClass>();
Run Code Online (Sandbox Code Playgroud)
我很欣赏这AddScopedInterfaceAndClass不是一个完美的名字 - 这只是一个展示这个想法的例子.此外,还有一个缺点,你必须记住使用此扩展而不是AddScoped.
注意:您可以AddScoped通过删除第二个generic(TClass)来简化扩展方法中的第二个,因为这是由编译器推断的.
| 归档时间: |
|
| 查看次数: |
729 次 |
| 最近记录: |