ASP.NET Core技术研究-探秘依赖注入框架
ASP.NET Core在底层内置了一个依赖注入框架,通过依赖注入的方式注册服务、提供服务。依赖注入不仅服务于ASP.NET Core自身,同时也是应用程序的服务提供者。 毫不夸张的说,ASP.NET Core通过依赖注入实现了各种服务对象的注册和创建,同时也实现了面向抽象的编程模式和编程体验,提升了应用程序的扩展性。 今天,我们普及一下ASP.NET Core中依赖注入的一些基本知识。 一、服务的注册 ? ?我们通过创建一个ASP.NET Core的项目,可以发现在Startup.cs 类中,有一个方法ConfigureServices,这个方法的注释是这样的: ? ? ?This method gets called by the runtime. Use this method to add services to the container. ? ? ? 在ConfigureServices方法中我们可以将通过ASP.NET Core内置的依赖注入框架实现服务的的注册。 ? 这个方法有个参数:IServiceCollection,见名知意,服务集合。 ? ASP.NET Core内置的依赖注入框架将服务注册信息存储到一个实现了IServiceCollection接口的对象中。默认情况下这个接口的实现类是ServiceCollection,以下是这个类的说明: ??https://docs.microsoft.com/en-us/dotnet/api/microsoft.extensions.dependencyinjection.servicecollection?view=dotnet-plat-ext-3.1 ? 通过这个接口和类实现,我们可以发现,注册服务其实就是将一个服务的ServiceDescriptor对象添加到ServiceCollection集合中。 ? 例如: public void ConfigureServices(IServiceCollection services)
{
services.Add(new ServiceDescriptor(typeof(IUserRepository),new UserRepository()));
services.AddControllers();
}
? ?ServiceDescriptor可以理解为对某个服务注册项的描述。ASP.NET Core的依赖注入容器IServiceProvider通过ServiceDescriptor的信息,动态创建服务的实例Instance.? ? ?我们看一下这个ServiceDescriptor类: ? ? ? ?有几个关键的属性: ? ? ?1. ServiceType:服务的类型,例如服务接口的类型信息 ? ? ?2.?ImplementationType:服务的实现类型,例如服务接口实现类的类型信息 ? ? ?3.?ImplementationInstance:实现服务的实例,一般是服务单例模式场景下使用。?https://docs.microsoft.com/en-us/dotnet/api/microsoft.extensions.dependencyinjection.servicedescriptor.-ctor?view=dotnet-plat-ext-3.1#Microsoft_Extensions_DependencyInjection_ServiceDescriptor__ctor_System_Type_System_Object_ ? ? 4. Lifetime:服务生命周期:Scoped(同一个请求中同一个IServiceProvider提供的对象是同一个)、Singleton(单例)、Transient(每次从服务容器进行请求时创建) ? ? 5.?ImplementationFactory 服务实例创建工厂,自定义的IServiceProvider服务提供容器 ? 服务注册提供了一系列重载的方法,大家可以根据需要进行选择: ?? ? ? ?服务注册的过程中,涉及到了服务的生命周期的概念,接下来我们详细看一下。 二、服务生命周期 ? ?服务的生命周期设置,决定了服务提供容器IServiceProvider使用什么样的方式提供服务实例对象。正如上面第一章节所说的, ? ?ASP.NET Core服务依赖注入框架,支持三种类型的服务生命周期:
? 其中: ? ?Transient:暂时的,每次从服务容器进行请求时创建。?这种生存期适合轻量级、 无状态的服务。 ? ?Singleton:单一实例,在第一次请求时(或者在运行 Startup.ConfigureServices 并且使用服务注册指定实例时)创建的。每个后续请求都使用相同的实例。 ? ?Scoped:范围内的,作用域生存期服务,以每个客户端请求(连接)一次的方式创建。可以这么理解:同一个请求中同一个IServiceProvider提供的对象是同一个。 ? ?微软给了个例子不错:先注册服务,三种类型 public void ConfigureServices(IServiceCollection services)
{
第一个请求:? ? ? ? 控制器操作:
暂时性:d233e165-f417-469b-a866-1cf1935d2518
作用域:5d997e2d-55f5-4a64-8388-51c4e3a1ad19
单一实例:01271bc1-9e31-48e7-8f7c-7261b040ded9
实例:00000000-0000-0000-0000-000000000000
OperationService 操作:
暂时性:c6b049eb-1318-4e31-90f1-eb2dd849ff64
作用域:5d997e2d-55f5-4a64-8388-51c4e3a1ad19
单一实例:01271bc1-9e31-48e7-8f7c-7261b040ded9
实例:00000000-0000-0000-0000-000000000000
第二个请求: 第二个请求:
控制器操作:
暂时性:b63bd538-0a37-4ff1-90ba-081c5138dda0
作用域:31e820c5-4834-4d22-83fc-a60118acb9f4
单一实例:01271bc1-9e31-48e7-8f7c-7261b040ded9
实例:00000000-0000-0000-0000-000000000000
OperationService 操作:
暂时性:c4cbacb8-36a2-436d-81c8-8c1b78808aaf
作用域:31e820c5-4834-4d22-83fc-a60118acb9f4
单一实例:01271bc1-9e31-48e7-8f7c-7261b040ded9
实例:00000000-0000-0000-0000-000000000000
? ?大家可以根据实际的需要选择服务的生命周期,创建不同类型的服务。 三、服务的消费 ? 前面,我们将服务注册到IServiceCollection,ASP.NET Core服务提供容器IServiceProvider就可以根据IServiceCollection 创建具体类型的服务对象了。 ? 我们先看一下IServiceProvider接口,可以发现:只有一个GetService方法。 ?? ? ? 我们可以通过以下代码使用: public static void Main(string[] args)
{
var builder = CreateHostBuilder(args);
var host = builder.Build();
var userRepo = host.Services.GetService(typeof(IUserRepository)) as IUserRepository;
userRepo.AddUser("user");
host.Run();
}
?同时,我们更多常用的是: ?将服务通过ASP.NET Core依赖注入框架注入到控制器中 ?ASP.NET Core MVC 控制器通过构造函数显式请求依赖关系。即:通过构造函数注入服务的实现。 ?前面,我们通过ConfigureServices注册了服务IUserRepository,在Controller这一层如何消费使用这个服务呢?答案就是在Controller构造函数中注入。 ?看一段示例代码:(HomeController的构造函数中,增加了一个参数IUserRepository) public class HomeController : Controller
{
private readonly ILogger<HomeController> _logger;
private IUserRepository _userRepository;
public HomeController(ILogger<HomeController> logger,IUserRepository userRepository)
{
_logger = logger;
_userRepository = userRepository;
}
public IActionResult Index()
{
_userRepository.AddUser(new User() { });
return View();
}
public IActionResult Privacy()
{
return View();
}
[ResponseCache(Duration = 0,Location = ResponseCacheLocation.None,NoStore = true)]
public IActionResult Error()
{
return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier });
}
}
同时,ASP.NET Core MVC 控制器支持通过注解FromServicesAttribute, 将服务直接注入到Action方法中,而无需使用构造函数注入: public IActionResult Index([FromServices] IUserRepository userRepository)
{
userRepository.AddUser(new User() { });
return View();
}
ASP.NET Core除了支持将服务注入到控制器,同时还支持将服务依赖注入到视图,可以参考以下链接: ? ??https://docs.microsoft.com/zh-cn/aspnet/core/mvc/views/dependency-injection?view=aspnetcore-3.0 ? ? 以上是对ASP.NET Core依赖注入框架的研究,分享给大家。 ? ? 周国庆 ?2020/4/12 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
- ASP.NET和MySQL .Net Framework数据提供程序问题
- asp.net-mvc – 找不到CrystalImageHandler.aspx
- ASP.Net错误 – 类型与控件类型不兼容
- asp.net-mvc – 哪种类型的缓存适合在Umbraco项目中使用,如
- asp.net-mvc – MVC – 如何将模型从视图传递到控制器
- telerik – ASP.NET MVC2富文本编辑器
- asp.net – User.Identity.GetUserId()方法无法在Web Api 2
- 处理ASP.NET MVC中日期的最佳方法 – Javascript应用程序
- 回收ASP.NET应用程序是否会激起用户的兴趣?
- asp.net – 循环访问复选框列表
- ASP.Net – 在负载平衡环境中处理会话数据?
- asp.net-mvc – 生成的视图中的模型值错误
- asp.net-core – Asp.Net核心(Full .Net框架)与A
- ASP.NET 谨用 async/await
- asp.net-identity交易问题
- asp.net-core – ASP.NET Core 1.1中的multipart
- ASP.NET MVC 4 JSON绑定到视图模型 – 嵌套对象错
- asp.net-mvc – 在ASP.NET MVC中添加服务引用4
- asp.net-mvc – DesignPatterns:哪个最适合用于
- ASP.NET / C#:DropDownList SelectedIndexChang