理解ASP.NET Core 啟動(dòng)類(lèi)(Startup)
準(zhǔn)備工作:一份ASP.NET Core Web API應(yīng)用程序
當(dāng)我們來(lái)到一個(gè)陌生的環(huán)境,第一件事就是找到廁所在哪。
當(dāng)我們接觸一份新框架時(shí),第一件事就是找到程序入口,即Main方法
public class Program
{
    public static void Main(string[] args)
    {
        CreateHostBuilder(args).Build().Run();
    }
    public static IHostBuilder CreateHostBuilder(string[] args) =>
        Host.CreateDefaultBuilder(args)
            .ConfigureWebHostDefaults(webBuilder =>
            {
                webBuilder.UseStartup<Startup>();
            });
}
代碼很簡(jiǎn)單,典型的建造者模式:通過(guò)IHostBuilder創(chuàng)建一個(gè)通用主機(jī)(Generic Host),然后啟動(dòng)它(至于什么是通用主機(jī),咱們后續(xù)的文章會(huì)說(shuō)到)。咱們不要一上來(lái)就去研究CreateDefaultBuilder、ConfigureWebHostDefaults這些方法的源代碼,應(yīng)該去尋找能看的見(jiàn)、摸得著的,很明顯,只有Startup。
Startup類(lèi)
Startup類(lèi)承擔(dān)應(yīng)用的啟動(dòng)任務(wù),所以按照約定,起名為Startup,不過(guò)你可以修改為任意類(lèi)名(強(qiáng)烈建議類(lèi)名為Startup)。
默認(rèn)的Startup結(jié)構(gòu)很簡(jiǎn)單,包含:
- 構(gòu)造函數(shù)
 Configuration屬性ConfigureServices方法Configure方法
public class Startup
{
    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }
    public IConfiguration Configuration { get; }
    // This method gets called by the runtime. Use this method to add services to the container.
    // 該方法由運(yùn)行時(shí)調(diào)用,使用該方法向DI容器添加服務(wù)
    public void ConfigureServices(IServiceCollection services)
    {
    }
    // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
    // 該方法由運(yùn)行時(shí)調(diào)用,使用該方法配置HTTP請(qǐng)求管道
    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
    }
}
Startup構(gòu)造函數(shù)
當(dāng)使用通用主機(jī)(Generic Host)時(shí),Startup構(gòu)造函數(shù)支持注入以下三種服務(wù)類(lèi)型:
IConfigurationIWebHostEnvironmentIHostEnvironment
public Startup(
    IConfiguration configuration,
    IHostEnvironment hostEnvironment,
    IWebHostEnvironment webHostEnvironment)
{
    Configuration = configuration;
    HostEnvironment = hostEnvironment;
    WebHostEnvironment = webHostEnvironment;
}
public IConfiguration Configuration { get; }
public IHostEnvironment HostEnvironment { get; set; }
public IWebHostEnvironment WebHostEnvironment { get; set; }
這里你會(huì)發(fā)現(xiàn) HostEnvironment 和 WebHostEnvironment 的實(shí)例是同一個(gè)。別著急,后續(xù)文章我們聊到Host的時(shí)候,你就明白了。
ConfigureServices
- 該方法是可選的
 - 該方法用于添加服務(wù)到DI容器中
 - 該方法在
Configure方法之前被調(diào)用 - 該方法要么無(wú)參數(shù),要么只能有一個(gè)參數(shù)且類(lèi)型必須為
IServiceCollection - 該方法內(nèi)的代碼大多是形如
Add{Service}的擴(kuò)展方法 
常用的服務(wù)有(部分服務(wù)框架已默認(rèn)注冊(cè)):
AddControllers:注冊(cè)Controller相關(guān)服務(wù),內(nèi)部調(diào)用了AddMvcCore、AddApiExplorer、AddAuthorization、AddCors、AddDataAnnotations、AddFormatterMappings等多個(gè)擴(kuò)展方法AddOptions:注冊(cè)O(shè)ptions相關(guān)服務(wù),如IOptions<>、IOptionsSnapshot<>、IOptionsMonitor<>、IOptionsFactory<>、IOptionsMonitorCache<>等。很多服務(wù)都需要Options,所以很多服務(wù)注冊(cè)的擴(kuò)展方法會(huì)在內(nèi)部調(diào)用AddOptionsAddRouting:注冊(cè)路由相關(guān)服務(wù),如IInlineConstraintResolver、LinkGenerator、IConfigureOptions<RouteOptions>、RoutePatternTransformer等AddAddLogging:注冊(cè)Logging相關(guān)服務(wù),如ILoggerFactory、ILogger<>、IConfigureOptions<LoggerFilterOptions>>等AddAuthentication:注冊(cè)身份認(rèn)證相關(guān)服務(wù),以方便后續(xù)注冊(cè)JwtBearer、Cookie等服務(wù)AddAuthorization:注冊(cè)用戶(hù)授權(quán)相關(guān)服務(wù)AddMvc:注冊(cè)Mvc相關(guān)服務(wù),比如Controllers、Views、RazorPages等AddHealthChecks:注冊(cè)健康檢查相關(guān)服務(wù),如HealthCheckService、IHostedService等
Configure
- 該方法是必須的
 - 該方法用于配置HTTP請(qǐng)求管道,通過(guò)向管道添加中間件,應(yīng)用不同的響應(yīng)方式。
 - 該方法在
ConfigureServices方法之后被調(diào)用 - 該方法中的參數(shù)可以接受任何已注入到DI容器中的服務(wù)
 - 該方法內(nèi)的代碼大多是形如
Use{Middleware}的擴(kuò)展方法 - 該方法內(nèi)中間件的注冊(cè)順序與代碼的書(shū)寫(xiě)順序是一致的,先注冊(cè)的先執(zhí)行,后注冊(cè)的后執(zhí)行
 
常用的中間件有
UseDeveloperExceptionPage:當(dāng)發(fā)生異常時(shí),展示開(kāi)發(fā)人員異常信息頁(yè)。如圖

UseRouting:路由中間件,根據(jù)Url中的路徑導(dǎo)航到對(duì)應(yīng)的Endpoint。必須與UseEndpoints搭配使用。UseEndpoints:執(zhí)行路由所選擇的Endpoint對(duì)應(yīng)的委托。UseAuthentication:身份認(rèn)證中間件,用于對(duì)請(qǐng)求用戶(hù)的身份進(jìn)行認(rèn)證。比如,早晨上班打卡時(shí),管理員認(rèn)出你是公司員工,那么才允許你進(jìn)入公司。UseAuthorization:用戶(hù)授權(quán)中間件,用于對(duì)請(qǐng)求用戶(hù)進(jìn)行授權(quán)。比如,雖然你是公司員工,但是你是一名.NET開(kāi)發(fā)工程師,那么你只允許坐在.NET開(kāi)發(fā)工程師區(qū)域的工位上,而不能坐在老總的辦公室里。UseMvc:Mvc中間件。UseHealthChecks:健康檢查中間件。UseMiddleware:用來(lái)添加匿名中間件的,通過(guò)該方法,可以方便的添加自定義中間件。
省略Startup類(lèi)
另外,Startup類(lèi)也可以省略,直接進(jìn)行如下配置即可(雖然可以這樣做,但是不推薦):
public static IHostBuilder CreateHostBuilder(string[] args) =>
    Host.CreateDefaultBuilder(args)
        .ConfigureWebHostDefaults(webBuilder =>
        {
            // ConfigureServices 可以調(diào)用多次,最終會(huì)將結(jié)果聚合
            webBuilder.ConfigureServices(services =>
            {
            })
            // Configure 如果調(diào)用多次,則只有最后一次生效
            .Configure(app =>
            {
                var env = app.ApplicationServices.GetRequiredService<IWebHostEnvironment>();
            });
        });
IStartupFilter
public interface IStartupFilter
{
    Action<IApplicationBuilder> Configure(Action<IApplicationBuilder> next);
}
有時(shí),我們想要將一系列相關(guān)中間件的注冊(cè)封裝到一起,那么我們只需要通過(guò)實(shí)現(xiàn)IStartupFilter,并在Startup.ConfigureServices中配置IStartupFilter的依賴(lài)注入即可。
- 在
IStartupFilter中配置的中間件,總是比Startup類(lèi)中Configure方法中的中間件先注冊(cè);對(duì)于多個(gè)IStartupFilter實(shí)現(xiàn),執(zhí)行順序與服務(wù)注冊(cè)時(shí)的順序一致 
我們可以通過(guò)一個(gè)例子來(lái)驗(yàn)證一下中間件的注冊(cè)順序。
首先是三個(gè)IStartupFilter的實(shí)現(xiàn)類(lèi):
public class FirstStartupFilter : IStartupFilter
{
    public Action<IApplicationBuilder> Configure(Action<IApplicationBuilder> next)
    => app =>
    {
        app.Use((context, next) =>
        {
            Console.WriteLine("First");
            return next();
        });
        next(app);
    };
}
public class SecondStartupFilter : IStartupFilter
{
    public Action<IApplicationBuilder> Configure(Action<IApplicationBuilder> next)
    => app =>
    {
        app.Use((context, next) =>
        {
            Console.WriteLine("Second");
            return next();
        });
        next(app);
    };
}
public class ThirdStartupFilter : IStartupFilter
{
    public Action<IApplicationBuilder> Configure(Action<IApplicationBuilder> next)
    => app =>
    {
        app.Use((context, next) =>
        {
            Console.WriteLine("Third");
            return next();
        });
        next(app);
    };
}
接下來(lái)進(jìn)行注冊(cè):
public static IHostBuilder CreateHostBuilder(string[] args) =>
    Host.CreateDefaultBuilder(args)
        .ConfigureServices(services =>
        {
            // 第一個(gè)被注冊(cè)
            services.AddTransient<IStartupFilter, FirstStartupFilter>();
        })
        .ConfigureWebHostDefaults(webBuilder =>
        {
            webBuilder.UseStartup<Startup>();
        })
        .ConfigureServices(services => 
        {
            // 第三個(gè)被注冊(cè)
            services.AddTransient<IStartupFilter, ThirdStartupFilter>();
        });
        
public class Startup
{
    public void ConfigureServices(IServiceCollection services)
    {
        // 第二個(gè)被注冊(cè)
        services.AddTransient<IStartupFilter, SecondStartupFilter>();
    }
    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        // 第四個(gè)被注冊(cè)
        app.Use((context, next) =>
        {
            Console.WriteLine("Forth");
            return next();
        });
    }
}
最后通過(guò)輸出可以看到,執(zhí)行順序的確是這樣子的。
First
Second
Third
Forth
IHostingStartup
與IStartupFilter不同的是,IHostingStartup可以在啟動(dòng)時(shí)通過(guò)外部程序集向應(yīng)用增加更多功能。不過(guò)這要求必須調(diào)用ConfigureWebHost、ConfigureWebHostDefaults等類(lèi)似用來(lái)配置Web主機(jī)的擴(kuò)展方法
我們經(jīng)常使用的Nuget包
SkyApm.Agent.AspNetCore就使用了該特性。
下面我們就來(lái)看一下該如何使用它。
HostingStartup 程序集
要?jiǎng)?chuàng)建HostingStartup程序集,可以通過(guò)創(chuàng)建類(lèi)庫(kù)項(xiàng)目或無(wú)入口點(diǎn)的控制臺(tái)應(yīng)用來(lái)實(shí)現(xiàn)。
接下來(lái)咱們還是看一下上面提到過(guò)的SkyApm.Agent.AspNetCore:
using SkyApm.Agent.AspNetCore;
[assembly: HostingStartup(typeof(SkyApmHostingStartup))]
namespace SkyApm.Agent.AspNetCore
{
    internal class SkyApmHostingStartup : IHostingStartup
    {
        public void Configure(IWebHostBuilder builder)
        {
            builder.ConfigureServices(services => services.AddSkyAPM(ext => ext.AddAspNetCoreHosting()));
        }
    }
}
該HostingStartup類(lèi):
- 實(shí)現(xiàn)了
IHostingStartup接口 Configure方法中使用IWebHostBuilder來(lái)添加增強(qiáng)功能- 配置了
HostingStartup特性 
HostingStartup 特性
HostingStartup特性用于標(biāo)識(shí)哪個(gè)類(lèi)是HostingStartup類(lèi),HostingStartup類(lèi)需要實(shí)現(xiàn)IHostingStartup接口。
當(dāng)程序啟動(dòng)時(shí),會(huì)自動(dòng)掃描入口程序集和配置的待激活的的程序集列表(參見(jiàn)下方:激活HostingStarup程序集),來(lái)找到所有的HostingStartup特性,并通過(guò)反射的方式創(chuàng)建Startup并調(diào)用Configure方法。
using SkyApm.Agent.AspNetCore;
[assembly: HostingStartup(typeof(SkyApmHostingStartup))]
namespace SkyApm.Agent.AspNetCore
{
    internal class SkyApmHostingStartup : IHostingStartup
    {
        public void Configure(IWebHostBuilder builder)
        {
            builder.ConfigureServices(services => services.AddSkyAPM(ext => ext.AddAspNetCoreHosting()));
        }
    }
}
激活HostingStarup程序集
要激活HostingStarup程序集,我們有兩種配置方式:
1.使用環(huán)境變量(推薦)
使用環(huán)境變量,無(wú)需侵入程序代碼,所以我更推薦大家使用這種方式。
配置環(huán)境變量ASPNETCORE_HOSTINGSTARTUPASSEMBLIES,多個(gè)程序集使用分號(hào)(;)進(jìn)行分隔,用于添加要激活的程序集。變量WebHostDefaults.HostingStartupAssembliesKey就是指代這個(gè)環(huán)境變量的Key。
另外,還有一個(gè)環(huán)境變量,叫做ASPNETCORE_HOSTINGSTARTUPEXCLUDEASSEMBLIES,多個(gè)程序集使用分號(hào)(;)進(jìn)行分隔,用于排除要激活的程序集。變量WebHostDefaults.HostingStartupExcludeAssembliesKey就是指代這個(gè)環(huán)境變量的Key。
我們?cè)?launchSettings.json 中添加兩個(gè)程序集:
"environmentVariables": {
    "ASPNETCORE_HOSTINGSTARTUPASSEMBLIES": "SkyAPM.Agent.AspNetCore;HostingStartupLibrary"
}
2.在程序中配置
public static IHostBuilder CreateHostBuilder(string[] args) =>
    Host.CreateDefaultBuilder(args)
        .ConfigureWebHostDefaults(webBuilder =>
        {
            webBuilder.UseSetting(
                WebHostDefaults.HostingStartupAssembliesKey,
                "SkyAPM.Agent.AspNetCore;HostingStartupLibrary")
            .UseStartup<Startup>();
        });
這樣就配置完成了,很🐮🍺的一個(gè)功能點(diǎn)吧!
需要注意的是,無(wú)論使用哪種配置方式,當(dāng)存在多個(gè)HostingStartup程序集時(shí),將按配置這些程序集時(shí)的書(shū)寫(xiě)順序執(zhí)行 Configure方法。
多環(huán)境配置
一款軟件,一般要經(jīng)過(guò)需求分析、設(shè)計(jì)編碼,單元測(cè)試、集成測(cè)試以及系統(tǒng)測(cè)試等一系列測(cè)試流程,驗(yàn)收,最終上線。那么,就至少需要4套環(huán)境來(lái)保證系統(tǒng)運(yùn)行:
Development:開(kāi)發(fā)環(huán)境,用于開(kāi)發(fā)人員在本地對(duì)應(yīng)用進(jìn)行調(diào)試運(yùn)行Test:測(cè)試環(huán)境,用于測(cè)試人員對(duì)應(yīng)用進(jìn)行測(cè)試Staging:預(yù)發(fā)布環(huán)境,用于在正式上線之前,對(duì)應(yīng)用進(jìn)行集成、測(cè)試和預(yù)覽,或用于驗(yàn)收Production:生產(chǎn)環(huán)境,應(yīng)用的正式線上環(huán)境
環(huán)境配置方式
通過(guò)環(huán)境變量ASPNETCORE_ENVIRONMENT指定運(yùn)行環(huán)境
注意:如果未指定環(huán)境,默認(rèn)情況下,為 Production
在項(xiàng)目的Properties文件夾里面,有一個(gè)“l(fā)aunchSettings.json”文件,該文件是用于配置VS中項(xiàng)目啟動(dòng)的。
接下來(lái)我們就在launchSettings.json中配置一下。
先解釋一下該文件中出現(xiàn)的幾個(gè)參數(shù):
commandName:指定要啟動(dòng)的Web服務(wù)器,有三個(gè)可選值:
Project:?jiǎn)?dòng) Kestrel
IISExpress:?jiǎn)?dòng)IIS Express
IIS:不啟用任何Web服務(wù)器,使用IIS
dotnetRunMessages:bool字符串,指示當(dāng)使用 dotnet run 命令時(shí),終端能夠及時(shí)響應(yīng)并輸出消息,具體參考stackoverflow和github issuelaunchBrowser:bool值,指示當(dāng)程序啟動(dòng)后,是否打開(kāi)瀏覽器launchUrl:默認(rèn)啟動(dòng)路徑applicationUrl:應(yīng)用程序Url列表,多個(gè)URL之間使用分號(hào)(;)進(jìn)行分隔。當(dāng)launchBrowser為true時(shí),將{applicationUrl}/{launchUrl}作為瀏覽器默認(rèn)訪問(wèn)的UrlenvironmentVariables:環(huán)境變量集合,在該集合內(nèi)配置環(huán)境變量
{
  "$schema": "http://json.schemastore.org/launchsettings.json",
  "profiles": {
    // 如果不指定profile,則默認(rèn)選擇第一個(gè)
    // Development
    "ASP.NET.WebAPI": {
      "commandName": "Project",
      "dotnetRunMessages": "true",
      "launchBrowser": true,
      "launchUrl": "weatherforecast",
      "applicationUrl": "http://localhost:5000",
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Development"
      }
    },
    // Test
    "ASP.NET.WebAPI.Test": {
      "commandName": "Project",
      "dotnetRunMessages": "true",
      "launchBrowser": true,
      "launchUrl": "weatherforecast",
      "applicationUrl": "http://localhost:5000",
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Test"
      }
    },
    // Staging
    "ASP.NET.WebAPI.Staging": {
      "commandName": "Project",
      "dotnetRunMessages": "true",
      "launchBrowser": true,
      "launchUrl": "weatherforecast",
      "applicationUrl": "http://localhost:5000",
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Staging"
      }
    },
    // Production
    "ASP.NET.WebAPI.Production": {
      "commandName": "Project",
      "dotnetRunMessages": "true",
      "launchBrowser": true,
      "launchUrl": "weatherforecast",
      "applicationUrl": "http://localhost:5000",
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Production"
      }
    },
    // 用于測(cè)試在未指定環(huán)境時(shí),默認(rèn)是否為Production
    "ASP.NET.WebAPI.Default": {
      "commandName": "Project",
      "dotnetRunMessages": "true",
      "launchBrowser": true,
      "launchUrl": "weatherforecast",
      "applicationUrl": "http://localhost:5000"
    }
  }
}
配置完成后,就可以在VS上方工具欄中的項(xiàng)目啟動(dòng)處選擇啟動(dòng)項(xiàng)了
基于環(huán)境的 Startup
Startup類(lèi)支持針對(duì)不同環(huán)境進(jìn)行個(gè)性化配置,有三種方式:
- 1.將
IWebHostEnvironment注入 Startup 類(lèi) - 2.Startup 方法約定
 - 3.Startup 類(lèi)約定
 
1.將IWebHostEnvironment注入 Startup 類(lèi)
通過(guò)將IWebHostEnvironment注入 Startup 類(lèi),然后在方法中使用條件判斷書(shū)寫(xiě)不同環(huán)境下的代碼。該方式適用于多環(huán)境下,代碼差異較少的情況。
public class Startup
{
    public Startup(IConfiguration configuration, IWebHostEnvironment webHostEnvironment)
    {
        Configuration = configuration;
        WebHostEnvironment = webHostEnvironment;
    }
    public IConfiguration Configuration { get; }
    public IWebHostEnvironment WebHostEnvironment { get; }
    public void ConfigureServices(IServiceCollection services)
    {
        if (WebHostEnvironment.IsDevelopment())
        {
            Console.WriteLine($"{nameof(ConfigureServices)}: {WebHostEnvironment.EnvironmentName}");
        }
        else if (WebHostEnvironment.IsTest())
        {
            Console.WriteLine($"{nameof(ConfigureServices)}: {WebHostEnvironment.EnvironmentName}");
        }
        else if (WebHostEnvironment.IsStaging())
        {
            Console.WriteLine($"{nameof(ConfigureServices)}: {WebHostEnvironment.EnvironmentName}");
        }
        else if (WebHostEnvironment.IsProduction())
        {
            Console.WriteLine($"{nameof(ConfigureServices)}: {WebHostEnvironment.EnvironmentName}");
        }
    }
    public void Configure(IApplicationBuilder app)
    {
        if (WebHostEnvironment.IsDevelopment())
        {
            Console.WriteLine($"{nameof(Configure)}: {WebHostEnvironment.EnvironmentName}");
        }
        else if (WebHostEnvironment.IsTest())
        {
            Console.WriteLine($"{nameof(Configure)}: {WebHostEnvironment.EnvironmentName}");
        }
        else if (WebHostEnvironment.IsStaging())
        {
            Console.WriteLine($"{nameof(Configure)}: {WebHostEnvironment.EnvironmentName}");
        }
        else if (WebHostEnvironment.IsProduction())
        {
            Console.WriteLine($"{nameof(Configure)}: {WebHostEnvironment.EnvironmentName}");
        }
    }
}
public static class AppHostEnvironmentEnvExtensions
{
    public static bool IsTest(this IHostEnvironment hostEnvironment)
    {
        if (hostEnvironment == null)
        {
            throw new ArgumentNullException(nameof(hostEnvironment));
        }
        return hostEnvironment.IsEnvironment(AppEnvironments.Test);
    }
}
public static class AppEnvironments
{
    public static readonly string Test = nameof(Test);
}
2.Startup 方法約定
上面的方式把不同環(huán)境的代碼放在了同一個(gè)方法中,看起來(lái)比較混亂也不容易區(qū)分。因此我們希望ConfigureServices和Configure能夠根據(jù)不同的環(huán)境進(jìn)行代碼拆分。
我們可以通過(guò)方法命名約定來(lái)解決,約定Configure{EnvironmentName}Services和Configure{EnvironmentName}Services來(lái)裝載不同環(huán)境的代碼。如果當(dāng)前環(huán)境沒(méi)有對(duì)應(yīng)的方法,則使用原來(lái)的ConfigureServices和Configure方法。
我就只拿 Development 和 Production 舉例了
public class Startup
{
    // 我這里注入 IWebHostEnvironment,僅僅是為了打印出來(lái)當(dāng)前環(huán)境信息
    public Startup(IConfiguration configuration, IWebHostEnvironment webHostEnvironment)
    {
        Configuration = configuration;
        WebHostEnvironment = webHostEnvironment;
    }
    public IConfiguration Configuration { get; }
    public IWebHostEnvironment WebHostEnvironment { get; }
    #region ConfigureServices
    private void StartupConfigureServices(IServiceCollection services)
    {
        Console.WriteLine($"{nameof(ConfigureServices)}: {WebHostEnvironment.EnvironmentName}");
    }
    public void ConfigureDevelopmentServices(IServiceCollection services)
    {
        StartupConfigureServices(services);
    }
    public void ConfigureProductionServices(IServiceCollection services)
    {
        StartupConfigureServices(services);
    }
    public void ConfigureServices(IServiceCollection services)
    {
        StartupConfigureServices(services);
    }
    #endregion
    #region Configure
    private void StartupConfigure(IApplicationBuilder app)
    {
        Console.WriteLine($"{nameof(Configure)}: {WebHostEnvironment.EnvironmentName}");
    }
    public void ConfigureDevelopment(IApplicationBuilder app)
    {
        StartupConfigure(app);
    }
    public void ConfigureProduction(IApplicationBuilder app)
    {
        StartupConfigure(app);
    }
    public void Configure(IApplicationBuilder app)
    {
        StartupConfigure(app);
    } 
    #endregion
}
3.Startup 類(lèi)約定
該方式適用于多環(huán)境下,代碼差異較大的情況。
程序啟動(dòng)時(shí),會(huì)優(yōu)先尋找當(dāng)前環(huán)境命名符合Startup{EnvironmentName}的 Startup 類(lèi),如果找不到,則使用名稱(chēng)為Startup的類(lèi)
首先,CreateHostBuilder方法需要做一處修改
public static IHostBuilder CreateHostBuilder(string[] args) =>
    Host.CreateDefaultBuilder(args)
        .ConfigureWebHostDefaults(webBuilder =>
        {
            //webBuilder.UseStartup<Startup>();
            webBuilder.UseStartup(typeof(Startup).GetTypeInfo().Assembly.FullName);
        });
接下來(lái),就是為各個(gè)環(huán)境定義 Startup 類(lèi)了(我就只拿 Development 和 Production 舉例了)
public class StartupDevelopment
{
    // 我這里注入 IWebHostEnvironment,僅僅是為了打印出來(lái)當(dāng)前環(huán)境信息
    public StartupDevelopment(IConfiguration configuration, IWebHostEnvironment webHostEnvironment)
    {
        Configuration = configuration;
        WebHostEnvironment = webHostEnvironment;
    }
    public IConfiguration Configuration { get; }
    public IWebHostEnvironment WebHostEnvironment { get; }
    public void ConfigureServices(IServiceCollection services)
    {
        Console.WriteLine($"{nameof(ConfigureServices)}: {WebHostEnvironment.EnvironmentName}");
    }
    public void Configure(IApplicationBuilder app)
    {
        Console.WriteLine($"{nameof(Configure)}: {WebHostEnvironment.EnvironmentName}");
    }
}
public class StartupProduction
{
    public StartupProduction(IConfiguration configuration, IWebHostEnvironment webHostEnvironment)
    {
        Configuration = configuration;
        WebHostEnvironment = webHostEnvironment;
    }
    public IConfiguration Configuration { get; }
    public IWebHostEnvironment WebHostEnvironment { get; }
    public void ConfigureServices(IServiceCollection services)
    {
        Console.WriteLine($"{nameof(ConfigureServices)}: {WebHostEnvironment.EnvironmentName}");
    }
    public void Configure(IApplicationBuilder app)
    {
        Console.WriteLine($"{nameof(Configure)}: {WebHostEnvironment.EnvironmentName}");
    }
}
到此這篇關(guān)于理解ASP.NET Core 啟動(dòng)類(lèi)(Startup)的文章就介紹到這了,更多相關(guān)ASP.NET Core Startup內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
 c# Random快速連續(xù)產(chǎn)生相同隨機(jī)數(shù)的解決方案
在寫(xiě)數(shù)獨(dú)基類(lèi)的時(shí)候?yàn)榱水a(chǎn)生隨機(jī)數(shù)的時(shí)候遇到奇怪的問(wèn)題2009-03-03
 asp.net(c#)復(fù)數(shù)類(lèi)(復(fù)數(shù)加減乘除四則運(yùn)算)
asp.net(c#)復(fù)數(shù)類(lèi)(復(fù)數(shù)加減乘除四則運(yùn)算)...2007-06-06
 vs2012創(chuàng)建的ado.net模型無(wú)法實(shí)例化的解決方案
本文給大家分享的是升級(jí)vs2012后,發(fā)現(xiàn)創(chuàng)建數(shù)據(jù)模型無(wú)法實(shí)例化使用,嘗試了很多種方法,最后在度娘的幫助下,才解決了這個(gè)問(wèn)題,這里記錄下來(lái),分享給大家。2015-03-03
 ASp.net 文本框(TextBox)計(jì)算,判斷輸入的是否是數(shù)字
ASp.net文本計(jì)算,文本框數(shù)字輸入檢測(cè),文本框的TextChanged事件,同時(shí)在屬性的Auto Post Back設(shè)置為T(mén)rue2009-07-07
 asp.net richTextBox中高亮顯示選中字符串或文本
最近開(kāi)發(fā)程序需要對(duì)一段文本中的某個(gè)字符串進(jìn)行高亮顯示,網(wǎng)上找了下資料2011-11-11
 ASP.NET Core Zero使用Power Tool工具
這篇文章介紹了ASP.NET Core Zero使用Power Tool工具的方法,對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2022-02-02
 Win 2000下ASP.NET開(kāi)發(fā)環(huán)境的配置
Win 2000在默認(rèn)情況下是不支持ASP.NET的。必須對(duì)它進(jìn)行一個(gè)環(huán)境的配置,本文將圖文介紹,在配置過(guò)程中遇到困難的朋友可以參考下2012-11-11
 C#和asp.net中鏈接數(shù)據(jù)庫(kù)中參數(shù)的幾種傳遞方法實(shí)例代碼
這篇文章介紹了C#和asp.net中鏈接數(shù)據(jù)庫(kù)中參數(shù)的幾種傳遞方法實(shí)例代碼,有需要的朋友可以參考一下2013-10-10

