インフラジスティックス・ジャパン株式会社Blog

インフラジスティックス・ジャパン株式会社のチームメンバーが技術トレンド、製品Tips、サポート情報からライセンス、日々の業務から感じることなど、さまざまなトピックについてお伝えするBlogです。

BlazorにおけるDIのScopeについて

f:id:ykinfragistics:20211126145423p:plain

皆さん、こんにちは!
ソリューションコンサルタントの狩谷です。 この記事では、BlazorにおけるDIの各Scopeについて、Blazor Server、Blazor WebAssemblyそれぞれの観点で見てみようと思います。

DIとは?

DIとはDependency Injectionの略で、依存性注入と訳されます。クラスを疎結合にし、柔軟なソフトウェア開発を可能にします。 例えば、メール送信のためにサードパーティのライブラリがあるとします。通常、このライブラリを利用する場合は、ライブラリのクラスのインスタンスを作成して利用します。この方法ですと、ライブラリのクラスと使用するクラスが密結合になってしまいます。 DIをすると、インターフェイスを経由してクラスのインスタンスを取得できるため、クラス間を疎結合にできます。 DIの詳細については、ここでは述べませんので、他の記事や書籍等を参照してください。

DIのScopeとは?

DIによってクラスのインスタンスを柔軟に生成できますが、インスタンスを生成する際に、インタンスが有効な範囲を決められます。このインスタンスが有効な範囲がScopeになります。ASP.NET Core Blazorの標準のDIを利用する場合、Transient、Scoped、Singletonの3つの範囲でインスタンスを管理できます。それぞれ基本的な範囲は以下のようになりますが、Blazor ServerかBlazor WebAssemblyかによって動作に違いがあります。

範囲 説明
Transient コンポーネントにアクセスされるたびにインスタンスが生成されます。
Scoped 利用ユーザー単位でインスタンスが生成されます。各コンポーネント間で共通のインスタンスが利用されます。
Singleton アプリケーション全体でインスタンスが生成されます。そのため、異なるユーザー間でもインスタンスが共有されます。

Transientの動作については、Blazor Server、Blazor WebAssemblyの違いはありませんが、Scoped、Singletonについては動作に違いがあるため、それぞれ解説していきたいと思います。

Blazor Serverにおける各Scopeの動作について

Blazor Serverにおける各Scopeの動きを確認したいと思います。まずは、標準で生成されるCounterコンポーネントのカウント数を保持するサービスを作成します。

public class CounterService
{
    public int Value { get; set; }

    public void Increment()
    {
        Value++;
    }
}

Transientの場合

Program.csにて作成したCounterSerive.csをDIコンテナに登録します。 (.NET5までの場合は、Startup.csのpublic void ConfigureServices(IServiceCollection services)で登録してください。)

builder.Services.AddRazorPages();
builder.Services.AddServerSideBlazor();
builder.Services.AddSingleton<WeatherForecastService>();
builder.Services.AddTransient<CounterService>(); //追加

var app = builder.Build();

Counter.razorを修正します。

@page "/counter"
@inject CounterService CounterService

<PageTitle>Counter</PageTitle>

<h1>Counter</h1>

<p role="status">Current count: @CounterService.Value</p>

<button class="btn btn-primary" @onclick="CounterService.Increment">Click me</button>

@code {
}

動作を確認してみます。コンポーネントの表示を切り替えると、インスタンスが初期化されるため、カウントが0に戻ります。

Server_Transient.gif

Scopedの場合

今度は、CounterSerive.csをScopedでDIコンテナに登録します。

builder.Services.AddRazorPages();
builder.Services.AddServerSideBlazor();
builder.Services.AddSingleton<WeatherForecastService>();
builder.Services.AddScoped<CounterService>(); //追加

var app = builder.Build();

コンポーネントを切り替えても、Counterのカウントが保持されています。ただし、リロードするとカウントが初期化されてしまいます。

Server_Scoped.gif

Singletonの場合

最後に、CounterSerive.csをSingletonでDIコンテナに登録します。

builder.Services.AddRazorPages();
builder.Services.AddServerSideBlazor();
builder.Services.AddSingleton<WeatherForecastService>();
builder.Services.AddSingleton<CounterService>(); //追加

var app = builder.Build();

コンポーネントを切り替えても、Counterのカウントが保持され、別のブラウザー(別のユーザー)で表示しても同じカウントが表示されます。リロードした場合も0に戻らず、最新のカウント数が表示されます。

Server_Singleton.gif

Blazor ServerにおけるDIのScopeのまとめ

Blazor Serverは名前の通り、Server側でプロセスが実行されているため、Sigletonの場合は同一プロセス内でインスタンスが共有されます。そのため、複数のブラウザーや複数のユーザーでアクセスした場合に、同じインスタンスが使用されます。Scopedの場合は、クライアントとサーバー間のSignalR接続ごとにインスタンスが作成されます。そのため、接続が有効な限り同一のインスタンスが使用されます。ブラウザをリロードすると、再接続されるため、新しくインスタンスが生成されます。 図にしたものが以下のものになります。

image.png

Blazor WebAssemblyにおける各Scopeの動作について

続いて、Blazor WebAssemblyにおける各Scopeの動きを確認したいと思います。同様にCounterコンポーネントのカウント数を保持するサービスを使用します。

Transientの場合

動作を確認してみます。Blazor Serverの場合と同様に、コンポーネントの表示を切り替えると、インスタンスが初期化されるため、カウントが0に戻ります。

WASM_Transient.gif

Scoped、Singletonの場合

Blazor WebAssemblyの場合は、ScopedとSingletonの動作は同じ動作になります。これは、ブラウザのタブごとにWebAssemblyのプロセスが実行されるため、Singletonのプロセスが有効な範囲とScopedの範囲が同じ範囲になるためです。そのため、Singletonの場合でも、リロードすればインスタンスが再生成されます。タブが違えば別プロセスとなるため、別インスタンスとなります。

WASM_Scoped_Singleton.gif

Blazor WebAssemblyにおけるDIのScopeのまとめ

Blazor WebAssemblyでは、各タブは固有のプロセスとなるので、Scoped、Singletonでも同様の動きとなります。 ブラウザの各タブはそれぞれ独立したアプリケーションプロセスであり、共通の状態を共有しません。 図にしたものが以下のものになります。

image.png

まとめ

Blazor Server、Blazor WebAssemblyそれぞれにおいて、プロセスの実行環境が異なります。それぞれの環境の特徴を理解し、効果的にDIを活用できればと思います。

技術サポート・無料オンライン相談会をご利用ください

インフラジスティックスのUI製品は多くの機能を備えているためドキュメントの情報量も多く、なかなかお探しの情報に辿り着けない場合もあります。そういった際はお気軽に技術サポートや、製品導入支援担当との無料オンライン相談会をご予約いただくことで検証時間を節約可能ですので、ぜひご活用ください。
技術サポートへの問い合わせ方法を確認する
無料オンライン相談会を予約する