SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

マルチターゲットアプリ開発の新しいアプローチ~.NET 9 新テンプレートの基本~

.NET MAUI Blazorを使って、AI画像生成アプリのプロジェクトを作成する

マルチターゲットアプリ開発の新しいアプローチ~.NET 9 新テンプレートの基本~ 第2回

  • X ポスト
  • このエントリーをはてなブックマークに追加

サービスとして設計する

 マルチターゲットアプリを開発する際には、プラットフォーム間の違いを考慮する必要があります。その違いを吸収するために、処理をサービスとして定義します。またその実装は、DIを用いて切り替えるようにします。

FormFactorサービス

 テンプレートで生成されたプロジェクトには、すでにこの考え方を示すサンプルとして、FormFactorサービスが含まれています。このサービスは、実行中のプラットフォームやデバイスの種類を検出するための基本的なしくみを提供するものです。

 ImageGenerator.SharedプロジェクトのServicesフォルダにあるIFormFactor.csを見てみましょう。

[リスト5]IFormFactor.csの一部
public interface IFormFactor
{
    public string GetFormFactor();
    public string GetPlatform();
}

 ここではサービスのインターフェイス(IFormFactor)として、デバイスのフォームファクター(Phone、Tabletなど)と、プラットフォーム(iOS、Android、Webなど)を取得するためのメソッドを定義しています。

 このインターフェイスの実装は、MAUIプロジェクトとWebプロジェクトで異なります。まず、MAUIプロジェクト(ImageGeneratorプロジェクト)のServicesフォルダにあるFormFactor.csの実装を見てみましょう。

[リスト6]FormFactor.csの一部
public string GetFormFactor()
{
    return DeviceInfo.Idiom.ToString();
}
public string GetPlatform()
{
    return DeviceInfo.Platform.ToString() + " - " + DeviceInfo.VersionString;
}

 MAUIの実装では、DeviceInfoクラスを使用して実際のデバイス情報を取得しています。一方、Webプロジェクト(ImageGenerator.Webプロジェクト)のServicesフォルダにあるFormFactor.csは、次のようになっています。

[リスト7]FormFactor.csの一部
public string GetFormFactor()
{
    return "Web";
}

public string GetPlatform()
{
    return Environment.OSVersion.ToString();
}

 Webの実装では、GetFormFactorメソッドで固定の文字列(Web)を返し、GetPlatformメソッドでは、Environmentクラスを利用するというものになっています。

 このように、共通のインターフェイスを定義し、プラットフォームごとに異なる実装を提供するパターンは、マルチターゲットアプリ開発の基本的なアプローチとなるものです。

サービスの登録方法

 サービスの登録方法も確認しておきましょう。MAUIプロジェクトのMauiProgram.csとWebプロジェクトのProgram.csで、それぞれFormFactorサービスを登録していますが、両方のプロジェクトで同じAddSingletonメソッドを使用しています。

builder.Services.AddSingleton<IFormFactor, FormFactor>();

 AddSingletonメソッドでは、初回要求時にインスタンスが一つだけ作成され、アプリケーションの終了まで同じインスタンスが使用されます。

画像生成サービスの作成

 FormFactorサービスと同様のパターンで、画像生成サービスのインターフェイスも準備しておきましょう。ImageGenerator.Sharedプロジェクト内のServicesフォルダを右クリックし、[追加]-[クラス]を選択してから、項目でインターフェイスに変えます。

インターフェイスの作成
インターフェイスの作成

 ファイル名を、IImageGenerationService.csとして追加作成し、次のように定義を変更します。

[リスト8]IImageGenerationService.csの一部
public interface IImageGenerationService
{
    // 非同期で画像URLを返す
    Task<string> GenerateImageAsync(string prompt);
}

 ここで定義するのは、画像を指示する文字列をパラメータとし、生成された画像のURLを返す非同期メソッドです。

 次にこのインターフェイスの実装として、同じServicesフォルダにMockImageService.csを作成し、クラス定義を次のように変更します。

[リスト9]MockImageService.csの一部
public class MockImageService : IImageGenerationService
{
    // モック画像のURLを返す非同期メソッド
    public async Task<string> GenerateImageAsync(string prompt)
    {
        await Task.Delay(1500); // 生成の遅延をシミュレートする
        return "https://placehold.jp/512x512.png?text=AI%20Generated%20Image";
    }
}

 今回は実際の画像生成までは行わず、Task.Delayメソッドで待機した後にサンプル画像(モック画像)を指定しています。モック画像は、placehold.jpを利用しました。

 このモックサービスをそれぞれのプロジェクトに登録しておきましょう。MAUIプロジェクトのMauiProgram.csとWebプロジェクトのProgram.csで、FormFactorサービスの登録の後に、MockImageGenerationServiceを登録するコードを追加します。

builder.Services.AddSingleton<IFormFactor, FormFactor>();
builder.Services.AddSingleton<IImageGenerationService, MockImageService>();

 次に、先ほど作成したImageGeneration.razorに、作成したサービスを使用するコードを追加します。

[リスト10]ImageGeneration.razorの一部
@page "/generate"
@using ImageGenerator.Shared.Services
@inject IImageGenerationService ImageService

~中略~

@code {

~中略~

    private async Task GenerateImage()
    {
        ~中略~
        try
        {
            // サービスを使用して画像を生成
            imageUrl = await ImageService.GenerateImageAsync(prompt);
        }
        ~中略~
    }
}

 ファイル上部に、@using ImageGenerator.Shared.Servicesを追加して、サービスの名前空間を使用可能にし、@inject IImageGenerationService ImageServiceでサービスを注入します。そして、GenerateImageメソッド内では、注入されたサービスのGenerateImageAsyncメソッドを呼び出すようにします。

 サービスを利用することで、UIロジックとビジネスロジックが適切に分離され、コードの保守性が向上します。次回、このモックサービスを、実際の画像生成API(DALL-E 3)を呼び出す実装と置き換える予定です。実装を変更しても、サービスを呼び出すImageGeneration.razorのコードを修正する必要はありません。

依存性注入(DI)による実装切り替え
依存性注入(DI)による実装切り替え

各プラットフォームでの表示確認

 作成したアプリを実行して、各プラットフォームで表示を確認してみましょう。

Blazor Webアプリでの確認

 ソリューションエクスプローラーのImageGenerator.Webプロジェクトを右クリックし、「スタートアッププロジェクトに設定」を選択します。そして実行ボタンをクリックすると、ブラウザが開き、アプリが表示されます。

 ブラウザでアプリが表示されたら、メニューから「画像生成」をクリックし、適当にプロンプトを入力して「画像を生成」ボタンをクリックしてみましょう。固定のモック画像が表示されるはずです。入力するプロンプトには影響されません。

ブラウザで実行されたWebの画面
ブラウザで実行されたWebの画面

Windows(.NET MAUI)アプリでの確認

 同様に、ImageGeneratorプロジェクトを右クリックし、「スタートアッププロジェクトに設定」を選択します。そして、デバッグターゲットとして「Windows Machine」を選んで実行ボタンをクリックします。

 MAUIアプリが起動したら、「画像生成」メニューをクリックして機能を確認してみましょう。Webアプリと同じUIが表示され、同じ動作をするはずです。

Windows上で実行されたMAUIアプリの画面
Windows上で実行されたMAUIアプリの画面

 Androidやその他のプラットフォームでも同様に確認できますが、それには適切な開発環境のセットアップが必要です。次回以降、モバイル環境への適用についても解説する予定です。

最後に

 今回は、「.NET MAUI Blazor HybridアプリとWebアプリ」テンプレートを使って、プロジェクトの作成と基本的なUIコンポーネントの実装を行いました。画像生成のロジックをサービスとして作成したことでUIから分離され、保守性の高いコードとなっています。

 次回は、「画像生成コアロジックの実装」として、OpenAIのDALL-E 3 APIを使った画像生成ロジックを実装する予定です。

この記事は参考になりましたか?

  • X ポスト
  • このエントリーをはてなブックマークに追加
マルチターゲットアプリ開発の新しいアプローチ~.NET 9 新テンプレートの基本~連載記事一覧
この記事の著者

WINGSプロジェクト 高江 賢(タカエ ケン)

WINGSプロジェクトについて>有限会社 WINGSプロジェクトが運営する、テクニカル執筆コミュニティ(代表 山田祥寛)。主にWeb開発分野の書籍/記事執筆、翻訳、講演等を幅広く手がける。2018年11月時点での登録メンバは55名で、現在も執筆メンバを募集中。興味のある方は、どしどし応募頂きたい。著書記事多数。 RSS X: @WingsPro_info(公式)、@WingsPro_info/wings(メンバーリスト) Facebook

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

山田 祥寛(ヤマダ ヨシヒロ)

静岡県榛原町生まれ。一橋大学経済学部卒業後、NECにてシステム企画業務に携わるが、2003年4月に念願かなってフリーライターに転身。Microsoft MVP for Visual Studio and Development Technologies。執筆コミュニティ「WINGSプロジェクト」代表。主な著書に「独習シリーズ(Java・C#・Python・PHP・Ruby・JSP&サーブレットなど)」「速習シリーズ(ASP.NET Core・Vue.js・React・TypeScript・ECMAScript、Laravelなど)」「改訂3版JavaScript本格入門」「これからはじめるReact実践入門」「はじめてのAndroidアプリ開発 Kotlin編 」他、著書多数

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

  • X ポスト
  • このエントリーをはてなブックマークに追加
CodeZine(コードジン)
https://codezine.jp/article/detail/22264 2025/09/29 11:00

おすすめ

アクセスランキング

アクセスランキング

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー

アクセスランキング

アクセスランキング