是否可以为Asp.Net Core中的默认DI设置注入范围?我的意思是例如:
services.AddSingleton<IUser, UserService>
services.AddSingleton<IUser, UserService>
对于第二种配置,以某种方式指定应仅将其注入到HomeController中。与第一个不同,应该将其注入所有其他对象。默认的DI可以吗?
答案 0 :(得分:0)
我相信您可以为特定控制器指定特殊注入。
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
services.AddScoped<TestService>();
services.AddTransient(ctx =>
new HomeController(new TestService("Non-default value")));
}
此tutorial具有更深的解释。
第二种可能被认为是解决方法的方法是注册一个基于名称的函数,该函数返回不同的服务实现。我以前使用过like this。
答案 1 :(得分:0)
假设进行此注册,则依赖项注入容器应该如何知道应该将哪个“单身”(当其中有两个时不是一个单例)注入到HomeController或另一个服务中,而它们都只是依赖在IUser
上?
在您的情况下IUser
中,依赖项被注册为的类型是DI容器用来解析依赖项的“键”。因此,两个都依赖于IUser
的服务将以相同的方式解决它们的依赖关系。单例生存期意味着这两个服务将获得相同的实例。
服务注册通常也可以代替。因此,如果您有一个注册AddSingleton<X, Y>()
,然后又有另一个AddSingleton<X, Z>()
,则后者将替换。因此,所有依赖X
的服务都将收到Z
。
DI容器(包括ASP.NET Core附带的默认容器)通常确实支持通过解析IEnumerable<X>
来解析 all 注册。但是对于此示例,这仅意味着服务将同时获得Y
和Z
。
您正在寻找的最接近的东西是键控或命名依赖项。虽然这些在 some DI容器中受支持,但从技术上讲,它们不是依赖项注入的一部分,因此deliberately absent通常来自许多容器,包括ASP.NET Core。 See this answer,以获取更多详细信息并解决该问题。
要回到您的用例,您应该真正考虑一下您在这里实际做什么。如果您有两个UserService
的“单例”实例,那么您应该真正想到为什么的情况:为什么不只有一个?如果支持多个,为什么不将其注册为瞬态?
更重要的是,这两个实例之间可能会有什么不同?毕竟,它们都是同一实现的实例,因此它们可以做的事情不多。
如果您可以识别出这一点,并且还确认这确实使实例与众不同,那么也可以考虑将其拆分为类型层次结构。没有此处的用例很难解释这一点,但是您应该尝试以两个different interfaces that each do exactly what each dependent service type needs结尾。因此,HomeController
可以依赖IUserA
,其他人可以依赖IUserB
(请选择比这更好的名称)。
答案 2 :(得分:0)
我在这里回答了类似的问题,但是使用了作用域而不是单例:
How to register multiple implementations of the same interface in Asp.Net Core?
我的直觉是,这可能是您要实现的目标,或者可能是更好的方法,并且您可能会将User与UserService混淆了。当您具有同一接口的多个实现时,DI会将它们添加到集合中,因此可以使用typeof
从集合中检索所需的版本。
// In Startup.cs
public void ConfigureServices(IServiceCollection services)
{
services.AddScoped(IUserService, UserServiceA);
services.AddScoped(IUserService, UserServiceB);
services.AddScoped(IUserService, UserServiceC);
}
// Any class that uses the service(s)
public class Consumer
{
private readonly IEnumerable<IUserService> _myServices;
public Consumer(IEnumerable<IUserService> myServices)
{
_myServices = myServices;
}
public UserServiceA()
{
var userServiceA = _myServices.FirstOrDefault(t => t.GetType() == typeof(UserServiceA));
userServiceA.DoTheThing();
}
public UserServiceB()
{
var userServiceB = _myServices.FirstOrDefault(t => t.GetType() == typeof(UserServiceB));
userServiceB.DoTheThing();
}
public UseServiceC()
{
var userServiceC = _myServices.FirstOrDefault(t => t.GetType() == typeof(UserServiceC));
userServiceC.DoTheThing();
}
}