评论

ASP.NET Core 依赖注入系列二

原标题:ASP.NET Core 依赖注入系列二

5 ASP.NET Core 依赖注入生命周期

通过依赖注入创建的服务有自己的生命周期,这里有两个问题

1 他们什么时候被创建

2 他们在内存里面保存多久之后才会被GC移除

服务有3种生命周期

1 Transient - 每次请求都会被创建

2 Scoped - 每次每个客户端请求被创建

3 Singleton - 只创建一次

6 依赖注入方法

我们常用三个方法来注册服务分别是Transient, Scoped & Singleton

6.1 AddTransient

AddTransient 用Transient方式创建的服务,当服务被请求时创建,这也意味着每次请求DI都会创建一个新的实例,我们在上面的例子使用了AddTransient方式注入服务,每次在控制器中请求IRepository接口时,都会创建一个新的Repository.cs类对象

6.2 AddScoped

通过AddScoped方法注册的服务不像AddTransient 方法那样每次都被创建,实际上它复用了来自同一客户端的请求,这意味着,如果我们使用这个方法来代替AddTransient,那么Repository.cs类对象将只创建一个,并在浏览器的同一个请求后续中共享该实例,然而,如果我们从另一台电脑的浏览器请求该应用程序,那么(对于这个新客户端)将为每个后续请求创建并共享一个新服务

6.3 AddSingleton

AddSingleton方法仅仅在第一次请求时创建一个服务,它会在每个请求中复用,和AddScoped方法不一样,每个跨客户端的请求都会共享该服务

针对AddTransient, AddScoped & AddSingleton方法每个方法都有三种变体

1 <service, implType> 这种变体为每个依赖项创建一个实现类型的实例,在上面我们已经使用过这中场景

2 <service>这个变体注册单个类型的对象,我们前面也覆盖到了这种场景

3 <service>(factoryFunc)这种方式使用lambda表达式注册一个服务,我们可以添加我们逻辑,我们将在后面覆盖这种场景

7 通过例子来了解这三种类型

7.1 Transient服务的例子

Transient 服务必须在Program类中使用AddTransient方法 注册,我们有2个Transient服务在我们应用程序中,他们是Repository和ProductSum

builder.Services.AddTransient< IRepository, Repository>; builder.Services.AddTransient< ProductSum>;

ProductSum类在指定的构造函数指定了IRepository依赖

namespaceAspNetCore.DependencyInjection.Models { publicclassProductSum { publicIRepository Repository { get; set; } publicProductSum( IRepository repo) { Repository = repo; } publicdecimalTotal => Repository.Products.Sum(p => p.Price); } }

HomeController指定针对这两个服务的依赖

public HomeController(IRepository repository, ProductSum productSum) { _repository = repository; _productSum = productSum; }

在Repository.cs类中重写ToString方法,代码如下:

private string guid= Guid.NewGuid.ToString; public override string ToString { return guid; }

我们可以通过这个值来判断依赖注入什么时候以及如何创建这个Repository,接下来进入HomeController并且在Index的方法中添加2个ViewBag变量,第一 ViewBag变量将包含从Repository接受的GUID,第二个ViewBag变量包含从ProductSum服务接受的GUID

publicIActionResult Index( ) { ViewBag.HomeControllerGUID=_repository.ToString; ViewBag.TotalGUID = _productSum.ToString; returnView( newRepository.Products); }

现在运行应用程序我们将会在页面上看到显示的GUID

我们看到这里2个不同的Guids,因为通过浏览器调用HomeController类每次会创建2个Repository的对象,第一个对象通过Repository服务创建,第二个对象通过ProductSum服务创建(ProductSum在构造函数中有一个IRepository依赖)

这个实例没有共享,我们使用Scoped服务只有一个对象创建,这个对象和ProductSum服务共享, 接下来我们看一下Scoped服务例子

7.2 Scoped服务的例子

为了理解Scoped服务,在Program类中使用AddScoped方法注册Repository服务

builder.Services.AddScoped<IRepository, Repository>;

重新运行应用程序并且你将看到相同的GUIDS, 这意味着ServiceProvider创建了一个Repository对象类并且和ProductSum共享该实例,这是Scoped和Transient服务之间的不同

重新加载页面按下F5,你将看到新的GUID被生成(因为浏览器初始化了一个新的HTTP请求)

7.3 Singleton服务的例子

最后让我们看一下Singleton服务,因此通过使用AddSingleton方法修改Repository服务的注册方式

builder.Services.AddSingleton<IRepository,Repository>;

重新运行你的应用程序,你将看到这两个GUID值是相同的,刷新页面你注意GUID值并没有改变

第一次创建Repository对象它会在后面的每次请求共享该对象, 当我们有多个客户端在浏览器中请求HomeController只会创建一个Repository对象并且共享该对象,所有的客户端每次请求都会看到相同的值返回搜狐,查看更多

责任编辑:

平台声明:该文观点仅代表作者本人,搜狐号系信息发布平台,搜狐仅提供信息存储空间服务。
阅读 ()
大家都在看
推荐阅读