ASP.NET Core 依赖注入系列二

文章详细介绍了ASP.NETCore中的依赖注入生命周期,包括Transient(每次请求创建新实例)、Scoped(每个客户端请求创建一个实例)和Singleton(全局单例)三种模式,并通过示例代码解释了如何注册和使用这些服务。
摘要由CSDN通过智能技术生成

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依赖

namespace AspNetCore.DependencyInjection.Models
{
    public class ProductSum
    {
        public IRepository Repository { get; set; }
        public ProductSum(IRepository repo)
        {
            Repository = repo;
        }
        public decimal Total => 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

public IActionResult Index()
{
    ViewBag.HomeControllerGUID=_repository.ToString();
    ViewBag.TotalGUID = _productSum.ToString();
    return View(new Repository().Products);
}

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

cd33fd22b9d98e98ed386d436e50d529.png

我们看到这里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请求)

51a0f1252eaab709362e10d950dd2002.png

7.3 Singleton服务的例子

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

builder.Services.AddSingleton<IRepository,Repository>();

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

deafa507e8fdf285df3fa8af439e6d4c.png

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值