Skip to content

.NET Core 实战 [No.330~332] Startup

🏷️ 《.NET Core 实战》

上一篇博客中的默认 ASP.NET Core Web 项目代码中都有看到一个 Startup 类,通过 UseStartup 方法指定该类。

csharp
WebHost.CreateDefaultBuilder(args)
    .UseStartup<Startup>()
    .Build()
    .Run();

Startup 并未要求类名为 Startup ,可以自定义类名,但要求类必须包含约定的方法:

  • ConfigureServices

    这个方法是可选的,当需要向容器添加服务时才定义。

    csharp
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddScoped<ConcreteServiceA>();
    }
  • Configure

    **此方法是必需的,它支持参数的依赖注入,**要求必需包含 IApplicationBuilder 类型的参数。如果有其它参数存在,IApplicationBuilder 类型的参数要放在参数列表的第一位,其余参数将由依赖注入来赋值。

    csharp
    public void Configure(IApplicationBuilder app, IHostingEnvironment env, ConcreteServiceA a)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }
    
        app.Run(async (context) =>
        {
            await context.Response.WriteAsync("Hello World!");
        });
    
        a.Run();
    }

除了使用约定方法来创建定义 Startup 类之外,还可以通过实现 IStartup 接口来定义 Startup 类。IStartup 接口定义如下:

csharp
public interface IStartup
{
    void Configure(IApplicationBuilder app);
    IServiceProvider ConfigureServices(IServiceCollection services);
}

下面是一个实现 IStartup 接口的示例。

csharp
public class MyStartup : IStartup
{
    public void Configure(IApplicationBuilder app)
    {
        app.Run(async (context) =>
        {
            await context.Response.WriteAsync("Hello World!");
        });
    }

    public IServiceProvider ConfigureServices(IServiceCollection services)
    {
        return services.AddScoped<ConcreteA>()
            .BuildServiceProvider();
    }
}

另外,框架还提供了一个抽象类 StartupBase,这个类已经实现了 IStartup 接口。

csharp
public class MyStartup : StartupBase
{
    public override void Configure(IApplicationBuilder app)
    {
        app.Run(async (context) =>
        {
            await context.Response.WriteAsync("Hello World!");
        });
    }
}

由于这两种 Startup 类的实现并非约定,不能在 Configure 方法上接受依赖注入的对象,但可以通过构造函数参数来注入。

csharp
IHostingEnvironment _hostEnv;

public MyStartup(IHostingEnvironment env)
{
    _hostEnv = env;
}

但是若要接受在 ConfigureServices 方法中注册的依赖注入对象则无法实现。

定义 Startup 类只是为了配置应用程序时更方便,实际启动时可以不使用 Startup 类。

csharp
public static void Main(string[] args)
{
    CreateWebHostBuilder(args).Build().Run();
}

public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
    WebHost.CreateDefaultBuilder(args)
        .ConfigureServices(services =>
        {
            services.AddScoped<ConcreteServiceA>();
        })
        .Configure(app =>
        {
            app.Run(async (context) =>
            {
                await context.Response.WriteAsync("Hello World!");
            });
        });

参考:《.NET Core 实战:手把手教你掌握 380 个精彩案例》 -- 周家安 著