.Net Core依赖注入之生命周期
.Net Core可以使用以下任一生存期注册服务:
-
暂时
-
作用域
-
单例
下列各部分描述了上述每个生存期。 为每个注册的服务选择适当的生存期。
1、暂时
暂时生存期服务是每次从服务容器进行请求时创建的。 这种生存期适合轻量级、 无状态的服务。 向 AddTransient 注册暂时性服务。
在处理请求的应用中,在请求结束时会释放暂时服务。
2、作用域
作用域生存期服务针对每个客户端请求(连接)创建一次。 向 AddScoped 注册范围内服务。
在处理请求的应用中,在请求结束时会释放有作用域的服务。
使用 Entity Framework Core 时,默认情况下 AddDbContext 扩展方法使用范围内生存期来注册 DbContext 类型。
不要从单一实例解析范围内服务。 当处理后续请求时,它可能会导致服务处于不正确的状态。 可以:
-
从范围内或暂时性服务解析单一实例服务。
-
从其他范围内或暂时性服务解析范围内服务。
默认情况下在开发环境中,从具有较长生存期的其他服务解析服务将引发异常。
要在中间件中使用范围内服务,请使用以下方法之一:
-
将服务注入中间件的 Invoke 或 InvokeAsync 方法。 使用构造函数注入会引发运行时异常,因为它强制使范围内服务的行为与单一实例类似。 生存期和注册选项部分中的示例演示了 InvokeAsync 方法。
-
使用基于工厂的中间件。 使用此方法注册的中间件按客户端请求(连接)**,这也使范围内服务可注入中间件的 InvokeAsync 方法。
3、单例
创建单例生命周期服务的情况如下:
-
在首次请求它们时进行创建;或者
-
在向容器直接提供实现实例时由开发人员进行创建。 很少用到此方法。
每个后续请求都使用相同的实例。 如果应用需要单一实例行为,则允许服务容器管理服务的生存期。 不要实现单一实例设计模式,或提供代码来释放单一实例。 服务永远不应由解析容器服务的代码释放。 如果类型或工厂注册为单一实例,则容器自动释放单一实例。
向 AddSingleton 注册单一实例服务。 单一实例服务必须是线程安全的,并且通常在无状态服务中使用。
在处理请求的应用中,当应用关闭并释放 ServiceProvider 时,会释放单一实例服务。 由于应用关闭之前不释放内存,因此请考虑单一实例服务的内存使用。
框架还提供 TryAdd{LIFETIME} 扩展方法,只有当尚未注册某个实现时,才注册该服务。
在下面的示例中,对 AddSingleton 的调用会将 MyDependency 注册为 IMyDependency的实现。 对 TryAddSingleton 的调用没有任何作用,因为 IMyDependency 已有一个已注册的实现:
-
TryAdd
-
TryAddTransient
-
TryAddScoped
-
TryAddSingleton
public interface IMyDependency1 { }
public interface IMyDependency2 { }
public class MyDependency : IMyDependency1, IMyDependency2 { }
services.TryAddEnumerable(ServiceDescriptor.Singleton<IMyDependency1, MyDependency>());
services.TryAddEnumerable(ServiceDescriptor.Singleton<IMyDependency2, MyDependency>());
services.TryAddEnumerable(ServiceDescriptor.Singleton<IMyDependency1, MyDependency>());
服务注册通常与顺序无关,除了注册同一类型的多个实现时。