1. <output id="hzk7v"><pre id="hzk7v"><address id="hzk7v"></address></pre></output>
      <output id="hzk7v"></output>
    2. <nav id="hzk7v"><i id="hzk7v"><em id="hzk7v"></em></i></nav>
    3. <listing id="hzk7v"><delect id="hzk7v"><em id="hzk7v"></em></delect></listing>

      .NET Core源码解析配置文件及依赖注入

       更新时间£º2019年04月04日 09:08:23   作者£º依乐祝   我要评论

      这篇文章我?#24039;?#35745;了一些复杂的概念£¬因为要对ASP.NET Core的启动及运行原理¡¢配置文件的加载过程进行分析£¬依赖注入£¬控制反转等概念的讲解等
      写在前面

      上篇文章我给大家讲解了ASP.NET Core的概念及为什?#35789;?#29992;它£¬接着带着你一步一步的配置了.NET Core的开发环境并创建了一个ASP.NET Core的mvc项目£¬同时又通过一个实战教你如何在页面显示一个Content的列表¡£不知道你有没有跟着敲下代码£¬千万不要做眼高手低的人哦¡£

      这篇文章我们就会设计一些复杂的概念了£¬因为要对ASP.NET Core的启动及运行原理¡¢配置文件的加载过程进行分析£¬依赖注入£¬控制反转等概念的讲解等¡£

      俗话说£¬授人?#26434;?#19981;如授人?#26434;‹‚?#25152;以文章旨在带着大家分析源码£¬让大家能知其然更能知其所以然¡£为了?#36947;Á£?#32487;续使用上篇文章的例子了£¡

      ASP.NET Core启动源码解析

      这部分我就带着大家一起看下asp.net core项目的运行流程吧£¡顺带着了解下asp.net core的运行原理£¬说的不好的话£¬希望大家给以指正£¬从而能够正确的帮助更多的人¡£

      1.首先上一下上篇文章的项目结构吧£¬如下所示£¬熟悉C#的朋友应该知道£¬要找程序的入库£¬那么就应该找到Main方法¡£而asp.net core的main方法就在Program.cs文件中¡£

      2.打开后看到如下的代码£¬我加了注释£¬大伙将就看下£¬下面我们来一步一步的分析

      /// <summary>
       /// Main方法£¬程序的入口方法
       /// </summary>
       /// <param name="args"></param>
       public static void Main(string[] args)
       {
        CreateWebHostBuilder(args)//调用下面的方法£¬返回一个IWebHostBuilder对象
        .Build()//用上面返回的IWebHostBuilder对象创建一个IWebHost
        .Run();//运行上面创建的IWebHost对象从而运行我们的Web应用程序换句话说就是启动一个一直运行监听http请求的任务
       }
      
       public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
        WebHost.CreateDefaultBuilder(args)//使用默认的配置信息来初始化一个新的IWebHostBuilder实例
        .UseStartup<Startup>();// 为Web Host指定了Startup类

      3.可以看到asp.net core程序实际上就是一个控制台程序£¬运行一个webhost对象从而启动一个一直运行的监听http请求的任务¡£所以我们的重点就是分析一下这个WebHost创建的过程£º

      创建IWebHostBuilder-?#21453;?#24314;IWebHost-¡·然后运行创建的IWebHost¡£

      4.这里我们从IWebHostBuilder的Build分析下创建的过程£¬?#34892;?#36259;的朋友可以看下£¬没兴趣的朋友可以直接跳到下一个步骤继续阅读¡£

                      1.首先到aspnetcore的github开源地址https://github.com/aspnet/AspNetCore/tree/release/2.1 上去下载源码£¨我们使用的是2.1£©¡£然后使用vscode打开解压后的文件夹¡£至于vscode如何加载文件£¬你可以看我这篇文章使用Visual Studio Code开发.NET Core看这篇就够了 ¡£

                      2.根据IWebHostBuilder的命名空间我们找到了它的实现£¬路径为src/Hosting/Hosting/src/WebHostBuilder.cs

                      3.通过上面的代码我们可以看到首先是通过BuildCommonServices来构建一个ServiceCollection¡£为什么说这么?#30340;Ø£?#20808;让我们我们跳转到BuidCommonServices方法中看下吧¡£

      可以看到£¬var services = new ServiceCollection();首先new一个ServiceCollection然后往services里面注入很多内容£¬比如£ºWebHostOptions £¬IHostingEnvironment £¬IHttpContextFactory £¬IMiddlewareFactory 等等£¨其实这里已经设计到依赖注入的概念了£¬?#20154;?#32771;下吧£©£¬然后我们在后续就可以使用了£¡最后这个BuildCommonServices就返回了这个services对象¡£

                      4.在上面的依赖注入中有一个方法£¬不知道大家注意到没有£¬因为我们在步骤2贴出的代码里面有一个UseStartup<Startup>() 其实在上面的BuildCommonServices方法中也有对IStartup的注入的¡£首先£¬判断Startup类是否继承于IStartup接口£¬如果是继承的£¬那么就可以直接加入在services 里面去£¬如果不是继承的话£¬就需要通过ConventionBasedStartup(methods)把method转换成IStartUp后注入到services里面去¡£结合上面我们的代码£¬?#33756;?#25105;们平时用的时候注入的方式都是采用后者¡£

                      5.我们再回到build方法拿到了BuildCommonServices方法构建的ServiceCollection实例后£¬通过GetProviderFromFactory(hostingServices) 方法构造出了IServiceProvider 对象¡£到目前为止£¬IServiceCollection和IServiceProvider都拿到了¡£然后根据IServiceCollection和IServiceProvider对象构建WebHost对象¡£构造了WebHost实例还不能直接返回£¬还需要通过Initialize对WebHost实例进行初始化操作¡£那我们看看在初始化函数Initialize中£¬都做了什?#35789;?#24773;吧¡£

                      6.这里我们把代码导航到src/Hosting/Hosting/src/Internal/WebHost.cs找到Initialize方法¡£如下图所示£º主要就是一个EnsureApplicationServices 方法¡£

                      7.我们继续导?#35762;?#30475;这个方法的内容如下£º就是拿到Startup 对象£¬然后把_applicationServiceCollection 中的对象注入进去¡£

                      8.至此我们build中注册的对象以及StartUp中注册的对象?#23478;?#32463;加入到依赖注入容器中了£¬接下来就是Run起来了¡£这个run的代码在src\Hosting\Hosting\src\WebHostExtensions.cs中£¬代码如下£º

      WebHost执行RunAsync运行web应用程序并返回一个只有在触发或关闭令牌时才完成的任务£¨这里又涉及到异步编程的知识了£¬咱们以后再详细讲解£© ¡£这就是我们运行ASP.Net Core程序的时候£¬看到的那个命令行窗口了£¬如果不关闭窗口或者按Ctrl+C的话是无法结束的¡£

                      9.至此启动的过程的源码分析完成了¡£

      配置文件

      上面给大家介绍了ASP.NET Core的启动过程£¬中间牵扯到了一些依赖注入的概念¡£关于依赖注入的概念呢£¬我们后面再说£¬这里先给大家讲解下配置文件的加载过程¡£

      4.打开上篇文章我们创建的项目£¬并在appsettings.json里面加入如下内容£º

      {
       "Logging": {
       "LogLevel": {
       "Default": "Warning"
       }
       },
       "Content": {
       "Id": 1,
       "title": "title1",
       "content": "content1",
       "status": 1,
       "add_time": "2018-11-21 16:29",
       "modify_time": null
       },
       "AllowedHosts": "*"
      }

      5.然后在Startup类中ConfigureServices中注册TOptions对象如下所示£º

      services.Configure<Content>(Configuration.GetSection("Content"));//注册TOption实例对象

      这段代码也就是从appsettings.json这个配置文件中的Content这个节点匹配到Content这个对象上¡£

      6.修改下ContentController这个控制器代码如下£º

      private readonly Content contents;
       public ContentController(IOptions<Content> option)
       {
        contents = option.Value;
       }
       /// <summary>
       /// 首页显示
       /// </summary>
       /// <returns></returns>
       public IActionResult Index()
       {
      
        return View(new ContentViewModel { Contents=new List<Content> { contents} });
       }

      7.按下F5运行下£¬然后导航到Content目录看到如下页面£º说明成功从appsettings.json这个文件中加载了内容¡£这一切是怎么发生的呢£¿下面我们就一步一步的来分析¡£

      8.我们回过头来看我们的Main方法£¬发现里面有一个CreateDefaultBuilder方法£¬就是这个方法里面为我们做了一些默认的设置£¬然后加载我们的配置文件的£¡

      9.我们在源码里面找到CreateDefaultBuilder 的源码£¨反正我找了半天£¬起初在Hosting下面找£¬实际上在MetaPackages下面的£©£¬位置在src\MetaPackages\src\Microsoft.AspNetCore\WebHost.cs 有的人可能找不?#33050;¶£?#21487;以看到这个方法会在ConfigureAppConfiguration 的时候默认加载appsetting文件£¬并做一些初始的设置£¬所以我们不需要任何操作£¬就能加载appsettings 的内容了¡£

      10.既然知道了原理后£¬我们就试着重写下这个ConfigureAppConfiguration 然后加载我们自定义的json文件吧¡£

      11.鼠标右键新建一个Content.json文件£¬然后输入如下的内容£º

      {
       "ContentList": 
       {
       "Id": 1,
       "title": "title1 from diy json",
       "content": "content1 from diy json",
       "status": 1,
       "add_time": "2018-11-21 16:29",
       "modify_time": null
       }
      
      }

      12.然后打开Program.cs¡£按如下代码进行?#33041;še?/p>

      /// <summary>
       /// Main方法£¬程序的入口方法
       /// </summary>
       /// <param name="args"></param>
       public static void Main(string[] args)
       {
        CreateWebHostBuilder(args)//调用下面的方法£¬返回一个WebHostBuilder对象
        .Build()//用上面返回的WebHostBuilder对象创建一个WebHost
        .Run();//运行上面创建的WebHost对象从而运行我们的Web应用程序换句话说就是启动一个一直运行监听http请求的任务
       }
      
       public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
        WebHost.CreateDefaultBuilder(args)//使用默认的配置信息来初始化一个新的IWebHostBuilder实例
        .ConfigureAppConfiguration((hostingContext, config) =>
        {
        var env = hostingContext.HostingEnvironment;
      
        config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
         .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: true)
         .AddJsonFile("Content.json",optional:false,reloadOnChange:false)
         .AddEnvironmentVariables();
      
        })
        .UseStartup<Startup>();// 为Web Host指定了Startup类

      13.然后Startup里面ConfigureServices中的代码修改如下£º

      14.然后按下F5运行下代码吧£¬如下图所示£¬从我们最新添加的json文件中加载出来数据了¡£

      15.这里多讲一点£¬传统asp.net的web.config文件如果有更改的话是必须要重启站点才能使£¬配置文件生效的£¬但是asp.net core的配置文件是支持热更新的£¬及不重启网站也能加载更新£¬只需要设置一下属性即可£¬如下图所示£º

      16.配置文件的源码解读这块就到这里了¡£下面开始依赖注入的讲解¡£

      依赖注入与控制反转

      如果大家仔细阅读文章的话£¬相信已经看出来了£¬我上面提到过好?#22797;?#20381;赖注入的概念¡£那么究竟什?#35789;?#20381;赖注入呢£¿下面我们就拿我?#24039;?#38754;的ContentController来好好的来理解下¡£

      依赖注入£º当一个对象ContentController需要另一个对象Content来协同完成任务的时候£¬那么这个ContentController就对这个Content对象产生了依赖关系¡£那么在这个ContentController中£¬是怎么注入的呢£¿就是从控制器中注入的了£¬如下图所示£º

      从asp.net 转过来的你是不是想起了之前的千篇一律的new对象啊¡£没对象自己new£¨要是女朋友也能new多好啊¡­¡­£©当然除了单例对象£¬静态哈¡£

      这里又设计一个概念就是控制反转¡£

      ?#25970;词²Ã词?#25511;制反转呢£¿你上面看到没有£¬你自己new对象就是正转£¬因为你自己创建自己所要使用的对象£¬¡£那么这种不需要你自己new对象£¬而是直接传进来就是控制反转了¡££¨不知道比喻的恰不恰当哈£©

      依赖注入与控制反转你是否已经了解了呢£¬?#19981;?#24605;考的朋友可能会问了£¬那这个构造函数里面的IOptions<Content> option 又是怎么出来的£¿这里就要引入一个容器的概念了¡£

      什?#35789;?#23481;器呢£¿

      这里创建IOptions<Content> option 这个对象的东西就是容器¡£还记得上面我们分析源码的时候£¬IServiceCollection 里面注入了很多东西吗£¿其实就是往IServiceCollection 这个容器里面注入方法£¬这样其他地方使用的时候就能自动注入了¡£

      这就是容器的?#20040;¦£?#30001;容器来统一管理实例的创建和销毁£¬你只需要关心怎么用就行了£¬不需要关系怎么创建跟销毁¡£

      当然容器创建的实例都是有生命周期的£¬¡£下面罗列一下£¬就不过多的讲解了¡£

      • Transient£º 每一次访问都会创建一个新的实例
      • Scoped£º 在同一个Scope内只初始化一个实例 £¬可以理解为£¨ 每一个request级别只创建一个实例£¬同一个http request会在一个 scope内£©
      • Singleton £º整个应用程序生命周期以内只创建一个实例

      使用的方式也很简单£¬我会在接下来的课程中详细的通过实例来进行讲解!因为现在的例子还没发演示¡£

      总结

      本文一步一步带着你先分析了ASP.NET Core的启动过程及运行的原理£¬紧接着给你讲了配置文件的加载过程及原理£¬并通过示例代码演示了如何加载自定义的配置文件£¬最后引出了依赖注入以及控制反转的概念£¬并通过对我?#24039;?#38754;例子的分析来紧身对依赖注入以及控制反转的理解¡£至此让你知其然更知其所以然¡£对ASP.NET Core的原理相信你已经了然于胸了£¡那么接下来让我们再准备下dapper,vue以及git的快速入门就开始我们的asp.net core cms的实战课程吧£¡还是那句话基础很重要£¬基础打好£¬后面才能事半功倍¡£谢谢大家¡£

      相关文章

      最新评论

      3dÊÔ»úºÅÖвÊÍø

        1. <output id="hzk7v"><pre id="hzk7v"><address id="hzk7v"></address></pre></output>
          <output id="hzk7v"></output>
        2. <nav id="hzk7v"><i id="hzk7v"><em id="hzk7v"></em></i></nav>
        3. <listing id="hzk7v"><delect id="hzk7v"><em id="hzk7v"></em></delect></listing>

            1. <output id="hzk7v"><pre id="hzk7v"><address id="hzk7v"></address></pre></output>
              <output id="hzk7v"></output>
            2. <nav id="hzk7v"><i id="hzk7v"><em id="hzk7v"></em></i></nav>
            3. <listing id="hzk7v"><delect id="hzk7v"><em id="hzk7v"></em></delect></listing>