usomaru技術ぶろぐ

学んだことをちょこちょこメモ( ..)φ

【.NET6 C#】Program.csについての理解を深める

はじめに

.NET6になってStartup.csがなくなりProgram.csに統合されました。
そこで改めてProgram.csで何をやっているのかといつも設定してる内容を備忘録的にまとめました。
ASP.NET Core Web APIで作成した場合の例を載せています。

環境

いつも通り

Program.csの中身(.NET 6)

プロジェクトを作成すると以下のようなコードが自動生成されるかと思います。

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.

builder.Services.AddControllers();
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();

var app = builder.Build();

// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI();
}

app.UseHttpsRedirection();

app.UseAuthorization();

app.MapControllers();

app.Run();

以前まではStartup.csにDIの設定とか、ミドルウェアパイプラインの構築処理とかを記載し、Program.csにMain関数があり、プログラムを起動すると最初に呼ばれるという感じで2つあったのですが、統合されてしまいました。

この統合された書き方を「最上位レベルのステートメント」というようなのですが、こちらにチェックをいれると、Main関数がProgram.csに現れます。

namespace WebApplication2
{
    public class Program
    {
        public static void Main(string[] args)
        {
            var builder = WebApplication.CreateBuilder(args);

            // Add services to the container.

            builder.Services.AddControllers();
            // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
            builder.Services.AddEndpointsApiExplorer();
            builder.Services.AddSwaggerGen();

            var app = builder.Build();

            // Configure the HTTP request pipeline.
            if (app.Environment.IsDevelopment())
            {
                app.UseSwagger();
                app.UseSwaggerUI();
            }

            app.UseHttpsRedirection();

            app.UseAuthorization();

            app.MapControllers();

            app.Run();
        }
    }
}

プログラムファイルはCreate→Build→Runの3段階で作成されます。
コードをよく見るとその3段階の記述があります。

WebApplication.CreateBuilder

新しい書き方になってから突然現れました。
デフォルトでは、ASP.NET プラットフォームのいくつかの基本機能がセットアップされるみたいです。

  1. Sets up HTTP server (Kestrel)  
  2. Logging
  3. Configuration
  4. Dependency injection container
  5. Adds the following framework-provided services

インターフェースを見ると見覚えのあるものがありました。

Swaggerの設定

プロジェクトを作成するときに、「OpenAPIサポートを有効にする」という部分にチェックをつけると、自動的にSwaggerの設定を追加してプロジェクトを作成してくれます。

if文になっている部分(開発環境だけSwaggerを表示するというif文)を消すと、本番環境にデプロイした際にもSwaggerが見れます。

if (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI();
}

サービスクラスのDIの設定

Singletonの場合

builder.Services.AddSingleton<IUserService, UserService>();

DBConnectionの設定

DbConnection ConnectionFactoryResolver(DatabaseDomain databaseDomain)
{
    return new SqlConnection(builder.Configuration.GetConnectionString(databaseDomain.GetConnectionName()));
}
builder.Services.AddSingleton<DefaultDbConnectionFactory>(() => ConnectionFactoryResolver(DatabaseDomain.Default));

DatabaseDomainExtensionsクラスを作って👆で接続先を構成することで、可変にできるみたい。

public enum DatabaseDomain
{
    Default = 0,
    Hoge = 1,
}

public static class DatabaseDomainExtensions
{
    public static string GetConnectionName(this DatabaseDomain source)
    {
        switch (source)
        {
            case DatabaseDomain.Default:
                return "DefaultConnection";
            case DatabaseDomain.Hoge
                return "HogeConnection";
            default:
                throw new ArgumentException();
        }
    }
}
public delegate DbConnection DefaultDbConnectionFactory();

使うときは、使いたいクラスにかいてあげる。

public HogeRepository(DefaultDbConnectionFactory connectionFactory)
{
    _connectionFactory = connectionFactory;
}

AuthorizationとAzure系リソースを使った時の設定はまた次の機会に…

参考