(5/30)みんなで学ぶBlazor:依存性注入

(5/30)みんなで学ぶBlazor:依存性注入

問題です。なぜBlazorはWeatherForecastServiceがここで呼び出せることを知っているのでしょうか?

最終更新 2021/12/11 13:27
StrayaWorker
読了目安 2 分
カテゴリ
Blazor
テーマ
みんなで学ぶBlazorシリーズ
タグ
.NET C# ASP.NET Core Blazor

では、なぜBlazorがここでWeatherForecastServiceを呼び出せるのかという問題があります。

Program.csを開くと、次の行が見つかります。

builder.Services.AddSingleton<WeatherForecastService>();

このコードをコメントアウトし、ウェブページをリロードしてFetch dataメニューをクリックすると、ページの下部に次のような例外警告ブロックが表示されます(フッターに警告ブロックが1つだけ表示されます)。詳細な警告はターミナルの出力を確認してください。これは、FetchData.razorWeatherForecastServiceを呼び出そうとしているのに、このサービスを登録することをBlazorに伝えていないからです。

ページの例外警告

ターミナルの例外出力

警告の内容をコピーして確認すると、非常に明確です。

Cannot provide a value for property 'ForecastService' on type 'BlazorServer.Pages.FetchData'. There is no registered service of type 'BlazorServer.Data.WeatherForecastService'.

ただし、これはday03で説明した依存性注入とは異なります。依存性注入の目的は、高レベルのプログラムが低レベルのプログラムに依存せざるを得ない状況を解消し、結合度を下げることです。例えば、今日FetchData.razorが他のサービス、例えばNewWeatherForecastServiceの同名メソッドGetForecastAsyncを呼び出して10件のデータを取得する必要がある場合、WeatherForecastServiceを使用しているすべての箇所を修正しなければなりません。現在はデモの関係で数が少ないため影響は感じませんが、将来的に10~20箇所以上を修正する必要がある場合はどうでしょうか?

ここで依存性注入が活躍します。まずインターフェースを定義します。interface IWeatherForecastService

namespace BlazorServer.Data;

public interface IWeatherForecastService
{
	Task<WeatherForecast[]> GetForecastAsync(DateTime startDate);
}

中に必要なメソッドを記述します。Task<WeatherForecast[]> GetForecastAsync(DateTime startDate);

実装する必要はありません(インターフェースにも実装を記述できます。C# 8.0ではインターフェースにデフォルト実装を指定する新機能が導入され、既存の実装を拡張しやすくなり、AndroidやSwiftのAPIとの相互運用も可能になりました)。次に、WeatherForecastServiceNewWeatherForecastServiceIWeatherForecastServiceを継承させます。

サービスのインターフェース実装

Program.csでは、IWeatherForecastServiceNewWeatherForecastServiceを使用して登録するように変更します。

インターフェースによるサービスの注入

上のスクリーンショットのように、FetchData.razorでもIWeatherForecastServiceを注入するように変更します。

ページをリロードすると、データ件数が10件になっているのが確認できます。

10件のデータ表示

依存性注入の核心は「ある機能への依存性が注入によって行われ」、低レベルのプログラムを直接呼び出すのではなく、低レベルのプログラムのインターフェースを呼び出すことです。これにより、低レベルのプログラムが変更されても、呼び出し側のすべてのプログラムを修正する必要がなくなります。

注:筆者はこの記事を書き終えた後にライフサイクルを思い出しました。当初はgit rebaseを使って今回のコミットに戻ってDemoを追加しようと考えましたが、gitの「detached HEAD」のリスクがあるため、day07でライフサイクルを説明します。ご不便をおかけして申し訳ございません。

注:本記事のコードは.NET 6 + Visual Studio 2022でリファクタリングされています。原文のリンクからリファクタリング後のコードを比較して学習できます。ご一読いただきありがとうございます。原作者をサポートしてください。

さらに探索

関連読書

その他の記事
同じカテゴリ / 同じタグ 2021/12/25

(29/30)みんなで学ぶBlazor:Blazor単体テスト

システム開発において最も退屈なプロセスは、おそらくバグ修正です。特に、null オブジェクトにアクセスしようとするエラー(`Object reference not set to an instance of an object.`)は、多くの初心者が最初に直面する問題です。退屈なバグ修正から解放されるために、この記事では「単体テスト」を紹介します。

続きを読む
同じカテゴリ / 同じタグ 2021/12/25

(28/30)みんなで学ぶBlazor:ポリシーベースの認可

以前に「ASP.NET Core Identity」は「Claim」ベースの検証を使用すると述べましたが、実は「ASP.NET Core Identity」には異なる種類の認可方法があります。最も簡単な「ログイン認可」「ロール認可」「Claim認可」ですが、これらはすべて同じ方法で実現されています:原則認可(ポリシーベースの認可)です。

続きを読む