ASP.NET Core 2.1 でホスト環境ごとに実行するメソッドまたはクラスを切り替える

# はじめに

ホスト環境の ASPNETCORE_ENVIRONMENT 環境変数に応じて、Configure メソッド、ConfigureServices メソッド、あるいは Startup クラスごと切り替える方法をまとめます。


# ホスト環境の切り替え

先ずは、デバッグ開始時にホスト環境を切り替えられるようにします。

プロジェクトの Properties の下にある launchSettings.json の profiles を以下のように編集します。

![launchSettings.PNG](https://qiita-image-store.s3.amazonaws.com/0/141789/c36417d1-a190-6ffc-d4d5-6643f21bc9e6.png)

```json
  "profiles": {
    "Development": {
      "commandName": "Project",
      "launchBrowser": false,
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Development"
      },
      "applicationUrl": "https://localhost:5001"
    },
    "Production": {
      "commandName": "Project",
      "launchBrowser": false,
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Production"
      },
      "applicationUrl": "https://localhost:5001"
    }
  }
```

プロジェクトのプロパティの[デバッグ]メニューから編集することもできます。

![launchSettings2.PNG](https://qiita-image-store.s3.amazonaws.com/0/141789/fca43f43-ec2d-3797-56f2-0b0851911c8b.png)

これで、デバッグ開始時にホスト環境を Development と Production に切り替えることができるようになりました。

![profiles.png](https://qiita-image-store.s3.amazonaws.com/0/141789/8703d958-df25-c224-0e74-bbaf70e31c05.png)


# Configure メソッドと ConfigureServices メソッドを切り替える場合

Startup クラスに次のような命名規則にしたがってメソッドを作ります。

```csharp
Configure<環境変数名>
Configure<環境変数名>Services
```

例えば、Production 環境でのみ実行したい場合は、次のようにします。

```csharp
public void ConfigureProduction(IApplicationBuilder app, IHostingEnvironment 
{
    // Production 環境用の処理
}

public void ConfigureProductionServices(IServiceCollection services)
{
    // Production 環境用の処理
}
```

該当するメソッドが見つからない場合は、Configure メソッド、ConfigureServices メソッドが呼ばれます。


# Startup クラスごと切り替える場合

まず初めに、Program.cs にある CreateWebHostBuilder メソッドを、次のように編集します。

```csharp
public static IWebHostBuilder CreateWebHostBuilder(string[] args)
{
    var assemblyName = typeof(Startup).GetTypeInfo().Assembly.FullName;

    return WebHost.CreateDefaultBuilder(args)
      .UseStartup(assemblyName);
}
```

リフレクションを使って動的にクラスを指定する際、この assemblyName を使っているようですが、この辺のロジックはまだちゃんと理解できていないです。

[stack overflow - How to configure Startup class in Asp.Net Core
](https://stackoverflow.com/a/39256777)

あとは、Startup.cs に以下のような命名規則でクラスを作れば切り替えができます。

```csharp
Startup<環境変数名>
```

例えば、Production 環境で有効にしたい場合は次のようになります。

```csharp
public class StartupProduction
{
    public StartupProduction(IConfiguration configuration)
    {
        // Constructor
    }

    // Production 環境用の Configure、ConfigureServices メソッド
}
```

# おまけ：appsettings.json を切り替える

appsettings.json を以下の命名規則で用意すると、ホスト環境に応じてロードするファイルを切り替えられます。

```csharp
appsettings.<Development>.json
```

例えば、Production 環境でロードする場合のファイル名は、次のようになります。

```csharp
appsettings.Production.json
```

# サンプルコード

メソッドを切り替えるプロジェクトと、クラスごと切り替えるプロジェクトを一つのソリューションにまとめたサンプルを GitHub で公開しておきます。
実行されたメソッド名を、コンソールに表示します。
また、クラスごと切り替えるプロジェクトでは、ホスト環境に応じて appsettings.Development.json か appsettings.Production.json を読み込んでいます。

[GitHub: EnvironBasedClassAndMethodSample](https://github.com/tatsuteb/EnvironBasedClassAndMethodSample)


# 参考

[Use multiple environments in ASP.NET Core - Environment-based Startup class and methods](https://docs.microsoft.com/en-us/aspnet/core/fundamentals/environments?view=aspnetcore-2.1#environment-based-startup-class-and-methods)

[stack overflow - How to configure Startup class in Asp.Net Core
](https://stackoverflow.com/a/39256777)