zoukankan      html  css  js  c++  java
  • 第四节:配置的读取、StartUp类、内置依赖注入和扩展改造

    一. 配置的读取

      在Asp.Net Core中,有一个 appsettings.json 文件,用于存储相应的配置信息,读取的时,要通过构造函数注入:IConfiguration Configuration,来进行读取。

      下面是一段配置文件,我们来对其进行读取:

     

    读取代码:

     1 public IConfiguration Configuration { get; }
     2 public FirstController(IConfiguration configuration)
     3 {
     4      Configuration = configuration;
     5 }
     6 {
     7       var f0 = Configuration["MyFullName"];
     8       var f1 = Configuration["User:userName"];
     9       var f2 = Configuration["User:Child:childName"];
    10       var f3 = Configuration["StudentList:0:sName"];
    11       var f4 = Configuration["StudentList:1:sName"];
    12 }

    二. StartUp类

    1. 说明:

      StartUp类中包括两个方法,分别是ConfigureServices和Configure,前者主要用来注册服务,后者主要用来创建和配置请 求管道,然后在Main方法中进行调用:     

     WebHost.CreateDefaultBuilder(args).UseStartup<Startup>();

    2. ConfigureServices方法

    (1). 它在Configure方法调用之前,由主机调用。

    (2). 需要大量设置的功能,IServiceCollection 上有 Add{Service} 扩展方法,常见的如下:

      a:services.AddDbContext<ApplicationDbContext>(options =>options.UseSqlServer( Configuration.GetConnectionString("DefaultConnection")));

      b:services.AddDefaultIdentity<IdentityUser>().AddDefaultUI(UIFramework.Bootstrap4).AddEntityFrameworkStores<ApplicationDbContext>();

      c:services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);

    3. Configure方法

    (1).用于配置Http请求管道,主要通过IApplicationBuilder实例来配置。

    (2).常见的管道有:

      开发人员异常页(UseDeveloperExceptionPage)、

      HTTP严格传输安全性(UseHsts)、

      HTTPS重定向(UseHttpsRedirection)、

      静态文件(UseStaticFiles)、

      MVC(UseMvc)。

    三. 内置依赖注入和扩展改造

    1. 说明:

      这里不再介绍什么是IOC和DI,直接介绍内置依赖注入的使用方法和生命周期,最后介绍利用AutoFac进行替换内置IOC容器。事先准备好U1-U4四个类和IU1-IU4四个接口。

    接口和类的代码:

     1   public interface IU1
     2     {
     3         string guid { get; set; }
     4         string GetName();
     5     }
     6   public interface IU2
     7     {
     8         string guid { get; set; }
     9         string GetName();
    10     }
    11   public interface IU3
    12     {
    13         string guid { get; set; }
    14         string GetName();
    15     }
    16   public interface IU4
    17     {
    18         string guid { get; set; }
    19         string GetName();
    20     }
    接口
     1  public class U1 : IU1
     2     {
     3         public string guid { get; set; }
     4 
     5         public U1()
     6         {
     7             guid = System.Guid.NewGuid().ToString("N");
     8         }
     9 
    10         /// <summary>
    11         /// 调用方法的时候,是单例也没有用,每次调用都会变
    12         /// </summary>
    13         /// <returns></returns>
    14         public string GetName()
    15         {
    16             return System.Guid.NewGuid().ToString("N");
    17         }
    18     }
    19  public class U2 : IU2
    20     {
    21         public string guid { get; set; }
    22 
    23         public U2()
    24         {
    25             guid = System.Guid.NewGuid().ToString("N");
    26         }
    27 
    28         /// <summary>
    29         /// 调用方法的时候,是单例也没有用,每次调用都会变
    30         /// </summary>
    31         /// <returns></returns>
    32         public string GetName()
    33         {
    34             return System.Guid.NewGuid().ToString("N");
    35         }
    36     }
    37  public class U3 : IU3
    38     {
    39         public string guid { get; set; }
    40 
    41         public U3()
    42         {
    43             guid = System.Guid.NewGuid().ToString("N");
    44         }
    45 
    46         /// <summary>
    47         /// 调用方法的时候,是单例也没有用,每次调用都会变
    48         /// </summary>
    49         /// <returns></returns>
    50         public string GetName()
    51         {
    52             return System.Guid.NewGuid().ToString("N");
    53         }
    54     }
    55  public class U4 : IU4
    56     {
    57         public string guid { get; set; }
    58 
    59         public U4()
    60         {
    61             guid = System.Guid.NewGuid().ToString("N");
    62         }
    63 
    64         /// <summary>
    65         /// 调用方法的时候,是单例也没有用,每次调用都会变
    66         /// </summary>
    67         /// <returns></returns>
    68         public string GetName()
    69         {
    70             return System.Guid.NewGuid().ToString("N");
    71         }
    72     }

    2. 核心:

      利用IServiceCollection services这个对象进行注册,而这个对象在Startup类中的ConfigureServices中已经注入进去了, 也就是说我在自定义对象的注册是的时候,可以直接在ConfigureServices类中进行注册,然后在控制器中使用的时候通过构造函数进行注入即可。

    PS:我们也可以自己 IServiceCollection container = new ServiceCollection(); 然后进行注册(不推荐,特殊情况下可能这么用)

    3. 生命周期分为三种:

      瞬时的(AddTransient)、请求内单例(AddScoped)、单例(AddSingleton 两种写法)。

    4. 测试:

      两次访问该页面,发现ViewBag.r1 和 ViewBag.r2两次的值不同,ViewBag.r3和ViewBag.r4两次的值相同。

    代码分享:

     1  public void ConfigureServices(IServiceCollection services)
     2         {
     3             services.Configure<CookiePolicyOptions>(options =>
     4             {
     5                 // This lambda determines whether user consent for non-essential cookies is needed for a given request.
     6                 options.CheckConsentNeeded = context => true;
     7                 options.MinimumSameSitePolicy = SameSiteMode.None;
     8             });
     9             services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
    10 
    11             //自定义注册对象
    12             {
    13                 services.AddTransient<IU1, U1>();   //瞬时的
    14                 services.AddScoped<IU2, U2>();      //一次请求内是不变的
    15                 services.AddSingleton<IU3, U3>();  //单例的
    16                 services.AddSingleton<IU4>(new U4());  //单例的
    17 
    18             }
    19         }
     1   public class FirstController : Controller
     2     {
     3         public IU1 U1 { get; }
     4         public IU1 U11 { get; }
     5         public IU2 U2 { get; }
     6         public IU2 U22 { get; }
     7         public IU3 U3 { get; }
     8         public IU3 U33 { get; }
     9         public IU4 U4 { get; }
    10         public IU4 U44 { get; }
    11 
    12         public FirstController(IU1 u1, IU1 u11, IU2 u2, IU2 u22, IU3 u3, IU3 u33, IU4 u4, IU4 u44)
    13         {
    14             U1 = u1;
    15             U11 = u11;
    16             U2 = u2;
    17             U22 = u22;
    18             U3 = u3;
    19             U33 = u33;
    20             U4 = u4;
    21             U44 = u44;
    22         }
    23 
    24         public IActionResult Index()
    25         {
    26             bool a = object.ReferenceEquals(U1, U11);
    27             bool b = object.ReferenceEquals(U2, U22);
    28             bool c = object.ReferenceEquals(U3, U33);
    29             bool d = object.ReferenceEquals(U4, U44);
    30 
    31             //分两次请求来查看
    32             ViewBag.r1 = U1.guid;
    33             ViewBag.r2 = U2.guid;
    34             ViewBag.r3 = U3.guid;
    35             ViewBag.r4 = U4.guid;
    36 
    37             //下面是自己创建的的模式进行访问
    38              {
    39                     IServiceCollection container = new ServiceCollection();
    40                     container.AddTransient<IU2, U2>();
    41                     //要放在注册的后面
    42                     var provider = container.BuildServiceProvider();
    43                     IU2 user1 = provider.GetService<IU2>();
    44                     IU2 user2 = provider.GetService<IU2>();
    45                     bool cc = object.ReferenceEquals(user1, user2);47             } 
    48             return View();
    49         }
    50     }
    1 <div class="text-center">
    2     <h1 class="display-4">Welcome</h1>
    3     <p>瞬时的:@ViewBag.r1</p>
    4     <p>请求内单例:@ViewBag.r2</p>
    5     <p>全局单例写法1:@ViewBag.r3</p>
    6     <p>全局单例写法2:@ViewBag.r4</p>
    7 </div>

    补充:

      如果不想通过构造函数注入,则可以通过[FromServices]特性来给某个特定方法注入:

           如: public void Test(【FromServices】IU1 u1){    }。

    两次访问的请求结果

    5. 为什么要用AutoFac进行替换内置容器?

      因为某些特定的功能内置的容器不支持,比如:属性的注入、基于名称的注入、子容器、自定生存期管理、对迟缓初始化的 Func<T> 支持

    6. 用AutoFac替换的步骤

    (1). 通过Nuget安装AutoFac【4.9.2】和Autofac.Extensions.DependencyInjection【4.4.0】

    (2). 改造ConfigureServices中配置容器并返回IServiceProvider,配置代码详见具体类,注入的代码封装到DefaultModule。

     1         public IServiceProvider ConfigureServices(IServiceCollection services)
     2         {
     3             services.Configure<CookiePolicyOptions>(options =>
     4             {
     5                 // This lambda determines whether user consent for non-essential cookies is needed for a given request.
     6                 options.CheckConsentNeeded = context => true;
     7                 options.MinimumSameSitePolicy = SameSiteMode.None;
     8             });
     9             services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
    10 
    11             // Add Autofac
    12             var containerBuilder = new ContainerBuilder();
    13             containerBuilder.RegisterModule<DefaultModule>();
    14             containerBuilder.Populate(services);
    15             var container = containerBuilder.Build();
    16             return new AutofacServiceProvider(container);
    17         }
    DefaultModule代码分享
    特别注意:AutoFac的生命周期也有:瞬时的、单次请求内单例的、全局单例的。
     1   public class DefaultModule: Module
     2     {
     3         protected override void Load(ContainerBuilder builder)
     4         {
     5             //这里就是AutoFac的注入方式,下面采用常规的方式
     6             //详见:https://www.cnblogs.com/yaopengfei/p/9479268.html
     7             //官网:https://autofac.org/
     8 
     9             //特别注意:其中很大的一个变化在于,Autofac 原来的一个生命周期InstancePerRequest,将不再有效。正如我们前面所说的,整个request的生命周期被ASP.NET Core管理了,
    10             //所以Autofac的这个将不再有效。我们可以使用 InstancePerLifetimeScope ,同样是有用的,对应了我们ASP.NET Core DI 里面的Scoped。
    11 
    12             //瞬时请求(省略InstancePerDependency 也为瞬时)
    13             builder.RegisterType<U1>().As<IU1>().InstancePerDependency();
    14             //单次请求内单例
    15             builder.RegisterType<U2>().As<IU2>().InstancePerLifetimeScope();
    16             //全局单例
    17             builder.RegisterType<U3>().As<IU3>().SingleInstance();
    18             builder.RegisterType<U4>().As<IU4>().SingleInstance();
    19 
    20         }
    21     }

    (3). 其他都不变,可以继续沿用构造函数注入。

    参考文章:

      https://www.cnblogs.com/yaopengfei/p/9479268.html   (.Net 平台下的AutoFac的用法)

      https://www.cnblogs.com/jesse2013/p/di-in-aspnetcore.html

     

    !

    • 作       者 : Yaopengfei(姚鹏飞)
    • 博客地址 : http://www.cnblogs.com/yaopengfei/
    • 声     明1 : 本人才疏学浅,用郭德纲的话说“我是一个小学生”,如有错误,欢迎讨论,请勿谩骂^_^。
    • 声     明2 : 原创博客请在转载时保留原文链接或在文章开头加上本人博客地址,否则保留追究法律责任的权利。
     
  • 相关阅读:
    AutoLayout动画
    实现毛玻璃效果
    合并静态库
    GCDAsyncSocket~
    iOS下URL编码
    OC多线程之GCD ----- 2
    堆和栈的区别
    Effective Objective-C 2.0重读笔记---2
    Android手机端抓包方法
    Android APK反编译
  • 原文地址:https://www.cnblogs.com/yaopengfei/p/10754397.html
Copyright © 2011-2022 走看看