• ASP.NET Core 的 `Core` 有几种写法?


    一、概述

    本文将会根据情况持续更新。
    作为一个 FrameworkASP.NET Core 提供了诸多的扩展点。使用内置的组件和默认的配置通常就能够满足部分需求,当需要扩展的时就需要先去找出这些扩展点。除了基于实际应用对 ASP.NET Core 进行扩展,也会故意搞一些不切实际的伪需求,解决一些不会存在的问题。这样的目的何在呢?一是为了加深对 ASP.NET Core 的理解,二是难保这些伪需求不会变成真需求。

    二、WebHost.CreateDefaultHostBuilder

    WebHost.CreateDefaultHostBuilder 静态方法用于创建 WebHostBuilder 对象,它有三个重载:

    public static IWebHostBuilder CreateDefaultBuilder();
    public static IWebHostBuilder CreateDefaultBuilder(string[] args);
    public static IWebHostBuilder CreateDefaultBuilder<TStartup>(string[] args) where TStartup : class;
    

    ASP.NET Core 项目模板使用的是第二个重载。第一个重载其实没多大必要,将第二个重载的 args 参数设置成默认为 null 也可以。使用第三个重载,可以少一次对 UseStartup<T> 的直接调用。

           public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
               WebHost.CreateDefaultBuilder<Startup>(args);
    

    备注:CreateDefaultBuilder 不能满足需求时,可自行通过 new 创建 WebHostBuilder 。比如 CreateDefaultBuilder 在创建 WebHostBuidler 调用了后者的 UseDefaultServiceProvider 扩展方法会导致使用默认的 DefaultServiceProviderFactory ,从而导致使用默认 DI 容器( ServiceProvider ),虽然之后可以替换成 Autofac 之类的,但可以控制直接使用而不是替换。

    三、IWebHostBuilder.UseStartup

    IWebHostBuilder.UseStartup 扩展方法用于使用 Startup,它有两个重载:

    public static IWebHostBuilder UseStartup(this IWebHostBuilder hostBuilder, Type startupType);
    public static IWebHostBuilder UseStartup<TStartup>(this IWebHostBuilder hostBuilder) where TStartup : class;
    

    ASP.NET Core 项目模板使用的是第二个重载,即泛型版本。泛型版本内部实际上调用的是非泛型版本。如果 Startup 不是定义在 ASP.NET Core Web 项目而是另一个程序集中,可先通过反射获取 Startup 的类型,然后调用非泛型版本。当然,通过反射来调用泛型版本也是可以的,但想不出这样做的理由。

    备注:
    Startup 会被注册为单例,多次调用 UseStartup 只有最后一个有效。
    应用名称默认是 Startup 类所在程序集的名称,如果将 Startup 类放在另一个程序集中,需要留意这一点。

    如果不使用 Startup 类,不注册服务,只配置中间件的话,可以使用 IWebHostBuilder.Configure 扩展方法:

    public static IWebHostBuilder Configure(this IWebHostBuilder hostBuilder, Action<IApplicationBuilder> configureApp);
    

    备注:Configure 看似是添加中间件的方法,其实不然。

    四、使用第三方依赖注入

    Startup 中替换依赖注入容器,以 Autofac 为例。第一种是实现 ConfigureContainer 方法:

           // ConfigureContainer is where you can register things directly
           // with Autofac. This runs after ConfigureServices so the things
           // here will override registrations made in ConfigureServices.
           // Don't build the container; that gets done for you. If you
           // need a reference to the container, you need to use the
           // "Without ConfigureContainer" mechanism shown later.
           public void ConfigureContainer(ContainerBuilder builder)
           {
               builder.RegisterModule(new AutofacModule());
           }
    

    第二种是实现 ConfigureServices 方法:

           // ConfigureServices is where you register dependencies. This gets
           // called by the runtime before the Configure method, below.
           public IServiceProvider ConfigureServices(IServiceCollection services)
           {
               // Add services to the collection.
               services.AddMvc();
               // Create the container builder.
               var builder = new ContainerBuilder();
               // Register dependencies, populate the services from
               // the collection, and build the container.
               //
               // Note that Populate is basically a foreach to add things
               // into Autofac that are in the collection. If you register
               // things in Autofac BEFORE Populate then the stuff in the
               // ServiceCollection can override those things; if you register
               // AFTER Populate those registrations can override things
               // in the ServiceCollection. Mix and match as needed.
               builder.Populate(services);
               builder.RegisterType<MyType>().As<IMyType>();
               this.ApplicationContainer = builder.Build();
               // Create the IServiceProvider based on the container.
               return new AutofacServiceProvider(this.ApplicationContainer);
           }
    

    第三种方法是采用自定义 IServiceProviderFactory 的方式,比如 Abp

      public static class AbpAutofacAbpApplicationCreationOptionsExtensions
      {
       public static void UseAutofac(this AbpApplicationCreationOptions options)
       {
         ContainerBuilder builder = new ContainerBuilder();
         options.Services.AddObjectAccessor<ContainerBuilder>(builder);
         options.Services.AddSingleton<IServiceProviderFactory<ContainerBuilder>>((IServiceProviderFactory<ContainerBuilder>) new AbpAutofacServiceProviderFactory(builder));
       }
      }
    

    备注:对于第三种方法,不用陷入先有鸡还是先有蛋的困境,WebHostBuilderBuild 方法会创建一个 HostingServiceProvider

    五、服务注册点

    包含名为 ConfigureServices 或类似的方法的接口和类:

    类/接口 程序集 命名空间 备注
    IStartup Microsoft.AspNetCore.Hosting.Abstractions Microsoft.AspNetCore.Hosting 接口。 实现类定义于应用。 配合 IWebHostBuilder.UseStartup 方法。
    Startup 自定义 自定义 定义于应用。不继承任何接口或类,实现 Configure 和 ConfigureServices 等方法。 配合 IWebHostBuilder.UseStartup 方法。
    IWebHostBuilder Microsoft.AspNetCore.Hosting.Abstractions Microsoft.AspNetCore.Hosting 接口。
    WebHostBuilder : IWebHostBuilder Microsoft.AspNetCore.Hosting Microsoft.AspNetCore.Hosting ConfigureServices 不会进行实际的服务注册操作,当调用 Build 方法时才注册。

    六、中间件注册点

    包含名为 Configure 或类似方法的接口和类:

    类/接口 程序集 命名空间 备注
    IStartup Microsoft.AspNetCore.Hosting.Abstractions Microsoft.AspNetCore.Hosting 接口。实现类定义于应用。 配合 IWebHostBuilder.UseStartup 方法。
    IHostingStartup Microsoft.AspNetCore.Hosting.Abstractions Microsoft.AspNetCore.Hosting 接口。
    Startup 自定义 自定义 定义于应用。不继承任何接口或类,实现 Configure 和 ConfigureServices 等方法。 配合 IWebHostBuilder.UseStartup 方法。
    IStartupFilter Microsoft.AspNetCore.Hosting.Abstractions Microsoft.AspNetCore.Hosting 接口。实现类定义于应用。需注册为服务。

    参考资料

    ASP.NET Core 中的应用启动
    在 ASP.NET Core 中使用 IHostingStartup 从外部程序集增强应用
    Autofac 集成 ASP.NET Core
    Abp 依赖注入
    ASP.NET Core 的扩展点

  • 相关阅读:
    撕裂寂寞
    创业中的“孙子兵法”
    生命的颜色占卜
    常常激励我们的36句话
    创建自己的3D虚拟身体!
    富人和穷人的八大差异
    有时,孤单是一种享受
    JavaScript类
    上网的十条基本礼节
    程序设计中的感悟
  • 原文地址:https://www.cnblogs.com/alby/p/aspnetcore-extension-points.html
Copyright © 2020-2023  润新知