通过依赖注入创建的服务有自己的生命周期,这里有两个问题
1 他们什么时候被创建
2 他们在内存里面保存多久之后才会被GC移除.
6 依赖注入方法
6.1 AddTransient
AddTransient 用Transient方式创建的服务,当服务被请求时创建,这也意味着每次请求DI都会创建一个新的实例,我们在上面的例子使用了AddTransient()方式注入服务,每次在控制器中请求IRepository接口时,都会创建一个新的Repository.cs类对象
针对AddTransient, AddScoped & AddSingleton方法每个方法都有三种变体
1 <service, implType>() 这种变体为每个依赖项创建一个实现类型的实例,在上面我们已经使用过这中场景
2 <service>()这个变体注册单个类型的对象,我们前面也覆盖到了这种场景
3 <service>(factoryFunc)这种方式使用lambda表达式注册一个服务,我们可以添加我们逻辑,我们将在后面覆盖这种场景
7.1 Transient服务的例子
builder.Services.AddTransient<IRepository, Repository>();
builder.Services.AddTransient<ProductSum>();
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);
}
}
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
我们看到这里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服务的例子
builder.Services.AddSingleton<IRepository,Repository>();