Share via


Blazor Web App を使って .NET MAUIBlazor Hybrid アプリを構築する

この記事では、Razor クラス ライブラリ (RCL) を介して共有ユーザー インターフェイスを使う、Blazor Web App による .NET MAUIBlazor Hybrid アプリの構築方法を説明します。

前提条件と準備手順

前提条件と準備手順については、「.NET MAUIBlazor Hybrid アプリを構築する」をご覧ください。 この記事で示すガイダンスに従う前に、.NET MAUIBlazor Hybrid チュートリアルに従って .NET MAUI 開発用にローカル システムを設定することをお勧めします。

.NET MAUIBlazor Web App のサンプル アプリ

Blazor サンプル GitHub リポジトリ (dotnet/blazor-samples) (.NET 8 以降) から、MauiBlazorWeb という名前のサンプル アプリを入手します

このサンプル アプリは、.NET MAUIBlazor Hybrid (ネイティブ、クロスプラットフォーム) アプリ、Blazor Web App、およびネイティブ アプリと Web アプリで使われる共有 UI (Razor コンポーネント) が含まれている Razor クラス ライブラリ (RCL) を含むスターター ソリューションです。

.NET MAUIBlazor Hybrid ソリューションの移行

サンプル アプリを使うのではなく、Visual Studio を使って、この項で示すガイダンスに従って既存の .NET MAUIBlazor Hybrid アプリを移行できます。

Blazor Web App プロジェクト テンプレートを使ってソリューションに新しいプロジェクトを追加します。 次のオプションを選択します。

  • プロジェクト名: ソリューションの名前を、.Web を追加して使います。 この記事の例では、次の名前付け規則を使うものとします:
    • ソリューション: MauiBlazorWeb
    • MAUI プロジェクト: MauiBlazorWeb.Maui
    • Blazor Web App: MauiBlazorWeb.Web
    • Razor クラス ライブラリ (RCL) (後の手順で追加): MauiBlazorWeb.Shared
  • 認証の種類: なし
  • HTTPSの構成: 選択されている (有効)
  • 対話型レンダリング モード: サーバー
  • 対話機能の場所 : グローバル
  • サンプル ページ: 選択されていない (無効)

MAUI アプリは常に対話形式で実行され、レンダリング モードを明示的に指定する Razor コンポーネント ページでエラーがスローされるため、[対話機能の場所] 設定が[グローバル] であることが重要です。 グローバル レンダリング モードを使わない場合は、この項で示すガイダンスに従った後、「Blazor レンダリング モードを使う」の項で示されている方法を実装する必要があります。 詳しくは、「BlazorWebView では ResolveComponentForRenderMode のオーバーライドを有効にする方法が必要 (dotnet/aspnetcore #51235)」をご覧ください。

新しい Razor クラス ライブラリ (RCL) プロジェクトをソリューションに追加します。 この記事の例では、このプロジェクトの名前が MauiBlazorWeb.Shared であることを前提としています。 ソリューションにこのプロジェクトを追加するときに [ページとビューのサポート] を選択しないでください。

MAUI プロジェクトと Blazor Web App プロジェクトの両方からこの RCL へのプロジェクト参照を追加します。

Components フォルダーとそのすべてのコンテンツを MAUI プロジェクトからこの RCL に移動します。 Components フォルダーが MAUI プロジェクトから削除されることを確認します。

ヒント

Visual Studio でフォルダーまたはファイルを移動するときは、切り取りと貼り付けの操作に、キーボード コマンドを使うか、右クリックでショートカット メニューを使います。 Visual Studio でフォルダーをドラッグした場合は、ある場所から別の場所にコピーされるだけであり、元のフォルダーを削除するにはさらに手順が必要です。

css フォルダーを MAUI プロジェクトの wwwroot フォルダーからこの RCL の wwwroot フォルダーに移動します。

この RCL の wwwroot フォルダーから次のファイルを削除します:

  • background.png
  • exampleJsInterop.js

この RCL で、ルートの _Imports.razor ファイルとこの RCL の Components フォルダー内のそのファイルを置き換えて、この RCL 内の既存のファイルを上書きし、Components フォルダー内の元のファイルを削除します。 このファイルを移動した後、それを開き、この RCL の名前空間に一致するように最後の 2 つの @using ステートメントの名前を変更します。 次の例では、この RCL の名前空間は MauiBlazorWeb.Shared です:

@using MauiBlazorWeb.Shared
@using MauiBlazorWeb.Shared.Components

RCL プロジェクトのルートで、次のファイルを削除します:

  • Component1.razor
  • ExampleJsInterop.cs

この RCL で、Components/Routes.razor ファイルを開き、MauiProgramRoutes に変更します:

- <Router AppAssembly="@typeof(MauiProgram).Assembly">
+ <Router AppAssembly="@typeof(Routes).Assembly">

MAUI プロジェクトで MainPage.xaml ファイルを開きます。 ContentPage 属性でこの RCL への xmlns:shared 参照を追加します。 次の例では、この RCL の名前空間は MauiBlazorWeb.Shared です。 clr-namespaceassemblyの両方に、正しい値を設定します:

xmlns:shared="clr-namespace:MauiBlazorWeb.Shared;assembly=MauiBlazorWeb.Shared"

また、MainPage.xaml ファイル内で、BlazorWebView のルート コンポーネントの ComponentTypelocal から shared に更新します:

- <RootComponent Selector="#app" ComponentType="{x:Type local:Components.Routes}" />
+ <RootComponent Selector="#app" ComponentType="{x:Type shared:Components.Routes}" />

MAUI プロジェクトで、wwwroot/index.html ファイルを開き、この RCL の静的アセット パスを指すようにスタイルシートを変更します。

次の行を削除します。

- <link rel="stylesheet" href="css/bootstrap/bootstrap.min.css" />
- <link rel="stylesheet" href="css/app.css" />

前述の行を次のマークアップに置き換えます。 次の例では、この RCL の静的アセット パスは _content/MauiBlazorWeb.Shared/ です:

<link rel="stylesheet" href="_content/MauiBlazorWeb.Shared/css/bootstrap/bootstrap.min.css" />
<link rel="stylesheet" href="_content/MauiBlazorWeb.Shared/css/app.css" />

Blazor Web App で、_Imports.razor ファイルを開き、この RCL に関して次の 2 つの @using ステートメントを追加します。 次の例では、この RCL の名前空間は MauiBlazorWeb.Shared です:

@using MauiBlazorWeb.Shared
@using MauiBlazorWeb.Shared.Components

Blazor Web App プロジェクトで、App コンポーネント (Components/App.razor) を開きます。 app.css スタイルシートを削除します:

- <link rel="stylesheet" href="app.css" />

前述の行をこの RCL の静的アセットのスタイルシートの参照に置き換えます。 次の例では、この RCL の静的アセット パスは _content/MauiBlazorWeb.Shared/ です:

<link rel="stylesheet" href="_content/MauiBlazorWeb.Shared/css/bootstrap/bootstrap.min.css" />
<link rel="stylesheet" href="_content/MauiBlazorWeb.Shared/css/app.css" />

Blazor Web App プロジェクトで、次のフォルダーとファイルを削除します:

  • Components/Layout フォルダー
  • Components/Routes.razor
  • Components/Pages/Home.razor
  • wwwroot/app.css

Blazor Web App の Program.cs ファイルを開き、この RCL の追加アセンブリをアプリに追加します。 次の例では、この RCL の名前空間は MauiBlazorWeb.Shared です:

app.MapRazorComponents<App>()
    .AddInteractiveServerRenderMode()
    .AddAdditionalAssemblies(typeof(MauiBlazorWeb.Shared._Imports).Assembly);

ソリューション エクスプローラーでプロジェクトを選択し、Visual Studio の [スタート] ボタンを使って MAUI プロジェクトを実行します。

ソリューション エクスプローラーで Blazor Web App プロジェクトを選択し、https ビルド構成で Visual Studio の [スタート] ボタンを使って Blazor Web App プロジェクトを実行します。

この RCL のアセンブリを解決できないというビルド エラーが発生した場合は、最初に RCL プロジェクトをビルドします。 ビルド時に MAUI プロジェクトのリソース エラーが発生した場合は、MAUI プロジェクトをリビルドしてエラーをクリアします。

Blazor レンダリング モードを使う

Blazor Web App 内の指定された対話機能の場所に対して Blazor レンダリング モードを適用するために、お客様のアプリの仕様に一致する次のいずれかのサブセクションで示すガイダンスに従います。ただし、MAUI プロジェクトでのレンダリング モード割り当ては無視します。

レンダリング モードと対話機能の仕様に関するサブセクション:

グローバルなサーバー対話機能

  • 対話型レンダリング モード:サーバー
  • 対話機能の場所: グローバル
  • ソリューション プロジェクト
    • MAUI (MauiBlazorWeb.Maui)
    • Blazor Web App (MauiBlazorWeb.Web)
    • RCL (MauiBlazorWeb.Shared): 各コンポーネントでレンダリング モードを設定しない、共有 Razor コンポーネントを含みます。

プロジェクト参照: MauiBlazorWeb.MauiMauiBlazorWeb.Web には MauiBlazorWeb.Sharedへのプロジェクト参照があります。

グローバルな自動または WebAssembly 対話機能

  • 対話型レンダリング モード: 自動または WebAssembly
  • 対話機能の場所: グローバル
  • ソリューション プロジェクト
    • MAUI (MauiBlazorWeb.Maui)
    • Blazor Web アプリ
      • サーバー プロジェクト: MauiBlazorWeb.Web
      • クライアント プロジェクト: MauiBlazorWeb.Web.Client
    • RCL (MauiBlazorWeb.Shared): 各コンポーネントでレンダリング モードを設定しない、共有 Razor コンポーネントを含みます。

プロジェクト参照:

  • MauiBlazorWeb.MauiMauiBlazorWeb.WebMauiBlazorWeb.Web.Client プロジェクトには、MauiBlazorWeb.Sharedへのプロジェクト参照があります。
  • MauiBlazorWeb.Web には、MauiBlazorWeb.Web.Client へのプロジェクト参照があります。

ページ/コンポーネントごとのサーバー対話機能

  • 対話型レンダリング モード:サーバー
  • 対話機能の場所: ページ/コンポーネントごと
  • ソリューション プロジェクト
    • MAUI (MauiBlazorWeb.Maui): MauiProgram.csInteractiveRenderSettings.ConfigureBlazorHybridRenderModes を呼び出します。
    • Blazor Web App (MauiBlazorWeb.Web): App コンポーネント (Components/App.razor) の HeadOutlet および Routes コンポーネントに @rendermode ディレクティブ属性を設定しません。
    • RCL (MauiBlazorWeb.Shared): 各コンポーネントで InteractiveServer レンダリング モードを設定する、共有 Razor コンポーネントを含みます。

MauiBlazorWeb.MauiMauiBlazorWeb.Web には MauiBlazorWeb.Shared へのプロジェクト参照があります。

次の InteractiveRenderSettings クラスをこの RCL に追加します。 このクラスのプロパティは、コンポーネントのレンダリング モードを設定するために使われます。

MAUI プロジェクトは既定では対話形式であるため、MAUI プロジェクト内のプロジェクト レベルでは、InteractiveRenderSettings.ConfigureBlazorHybridRenderModes を呼び出す以外のアクションは実行されません。

Web クライアント上の Blazor Web App の場合、それらのプロパティ値は RenderMode から割り当てられます。 MAUI プロジェクトのネイティブ クライアントの場合にコンポーネントが BlazorWebView に読み込まれると、レンダリング モードは割り当て解除 (null) されます。これは、ConfigureBlazorHybridRenderModes が呼び出されたときに MAUI プロジェクトによって明示的にレンダリング モードのプロパティが null に設定されるためです。

InteractiveRenderSettings.cs:

using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Web;

namespace MauiBlazorWeb.Shared;

public static class InteractiveRenderSettings
{
    public static IComponentRenderMode? InteractiveServer { get; set; } = 
        RenderMode.InteractiveServer;
    public static IComponentRenderMode? InteractiveAuto { get; set; } = 
        RenderMode.InteractiveAuto;
    public static IComponentRenderMode? InteractiveWebAssembly { get; set; } = 
        RenderMode.InteractiveWebAssembly;

    public static void ConfigureBlazorHybridRenderModes()
    {
        InteractiveServer = null;
        InteractiveAuto = null;
        InteractiveWebAssembly = null;
    }
}

MauiProgram.csMauiProgram.CreateMauiAppで、ConfigureBlazorHybridRenderModesを呼び出します:

InteractiveRenderSettings.ConfigureBlazorHybridRenderModes();

この RCL の _Imports.razor ファイル内で、次のグローバル静的 @using ディレクティブを追加してこのクラスのプロパティをコンポーネントで使えるようにします:

@using static InteractiveRenderSettings

Note

この RCL の InteractiveRenderSettings クラス プロパティによるレンダリング モードの割り当ては、一般的なスタンドアロン Blazor Web App とは異なります。 Blazor Web App では、レンダリング モードは、通常は Blazor Web App の _Import ファイル内の @using static Microsoft.AspNetCore.Components.Web.RenderMode ステートメントにより RenderMode で提供されます。

ページ/コンポーネントごとの自動対話機能

  • 対話型レンダリング モード: 自動
  • 対話機能の場所: ページ/コンポーネントごと
  • ソリューション プロジェクト
    • MAUI (MauiBlazorWeb.Maui): MauiProgram.csInteractiveRenderSettings.ConfigureBlazorHybridRenderModes を呼び出します。
    • Blazor Web アプリ
      • サーバー プロジェクト: MauiBlazorWeb.Web: App コンポーネント (Components/App.razor) の HeadOutlet および Routes コンポーネントに @rendermode ディレクティブ属性を設定しません。
      • クライアント プロジェクト: MauiBlazorWeb.Web.Client
    • RCL (MauiBlazorWeb.Shared): 各コンポーネントで InteractiveAuto レンダリング モードを設定する、共有 Razor コンポーネントを含みます。

プロジェクト参照:

  • MauiBlazorWeb.MauiMauiBlazorWeb.WebMauiBlazorWeb.Web.Client には、MauiBlazorWeb.Shared へのプロジェクト参照があります。
  • MauiBlazorWeb.Web には、MauiBlazorWeb.Web.Client へのプロジェクト参照があります。

この RCL に追加される、次の InteractiveRenderSettings クラスを追加します。 このクラスのプロパティは、コンポーネントのレンダリング モードを設定するために使われます。

MAUI プロジェクトは既定では対話形式であるため、MAUI プロジェクト内のプロジェクト レベルでは、InteractiveRenderSettings.ConfigureBlazorHybridRenderModes を呼び出す以外のアクションは実行されません。

Web クライアント上の Blazor Web App の場合、それらのプロパティ値は RenderMode から割り当てられます。 MAUI プロジェクトのネイティブ クライアントの場合にコンポーネントが BlazorWebView に読み込まれると、レンダリング モードは割り当て解除 (null) されます。これは、ConfigureBlazorHybridRenderModes が呼び出されたときに MAUI プロジェクトによって明示的にレンダリング モードのプロパティが null に設定されるためです。

InteractiveRenderSettings.cs:

using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Web;

namespace MauiBlazorWeb.Shared;

public static class InteractiveRenderSettings
{
    public static IComponentRenderMode? InteractiveServer { get; set; } = 
        RenderMode.InteractiveServer;
    public static IComponentRenderMode? InteractiveAuto { get; set; } = 
        RenderMode.InteractiveAuto;
    public static IComponentRenderMode? InteractiveWebAssembly { get; set; } = 
        RenderMode.InteractiveWebAssembly;

    public static void ConfigureBlazorHybridRenderModes()
    {
        InteractiveServer = null;
        InteractiveAuto = null;
        InteractiveWebAssembly = null;
    }
}

MauiProgram.csMauiProgram.CreateMauiAppで、ConfigureBlazorHybridRenderModesを呼び出します:

InteractiveRenderSettings.ConfigureBlazorHybridRenderModes();

この RCL の _Imports.razor ファイル内で、次のグローバル静的 @using ディレクティブを追加してこのクラスのプロパティをコンポーネントで使えるようにします:

@using static InteractiveRenderSettings

Note

この RCL の InteractiveRenderSettings クラス プロパティによるレンダリング モードの割り当ては、一般的なスタンドアロン Blazor Web App とは異なります。 Blazor Web App では、レンダリング モードは、通常は Blazor Web App の _Import ファイル内の @using static Microsoft.AspNetCore.Components.Web.RenderMode ステートメントにより RenderMode で提供されます。

ページ/コンポーネントごとの WebAssembly 対話機能

  • 対話型レンダリング モード: WebAssembly
  • 対話機能の場所: ページ/コンポーネントごと
  • ソリューション プロジェクト
    • MAUI (MauiBlazorWeb.Maui)
    • Blazor Web アプリ
      • サーバー プロジェクト: MauiBlazorWeb.Web: App コンポーネント (Components/App.razor) の HeadOutlet および Routes コンポーネントに @rendermode ディレクティブ属性を設定しません。
      • クライアント プロジェクト: MauiBlazorWeb.Web.Client
    • RCL
      • MauiBlazorWeb.Shared
      • MauiBlazorWeb.Shared.Client: 各コンポーネントで InteractiveWebAssembly レンダリング モードを設定する、共有 Razor コンポーネントを含みます。 .Shared.Client RCL は、.Shared RCL とは別に保持されます。これは、アプリで、WebAssembly で実行する必要があるコンポーネントを、サーバーで実行しサーバーに留まるコンポーネントとは別に保持する必要があるためです。

プロジェクト参照:

  • MauiBlazorWeb.MauiMauiBlazorWeb.Web には MauiBlazorWeb.Shared へのプロジェクト参照があります。
  • MauiBlazorWeb.Web には、MauiBlazorWeb.Web.Client へのプロジェクト参照があります。
  • MauiBlazorWeb.Web.ClientMauiBlazorWeb.Shared には MauiBlazorWeb.Shared.Client へのプロジェクト参照があります。

MauiBlazorWeb.Shared プロジェクトの Routes.razor ファイル内で、MauiBlazorWeb.Shared.Client プロジェクト アセンブリに関して Router コンポーネント インスタンスに次の AdditionalAssemblies パラメーターを追加します (その _Imports ファイルを使います):

<Router AppAssembly="@typeof(Routes).Assembly" 
        AdditionalAssemblies="new [] { typeof(MauiBlazorWeb.Shared.Client._Imports).Assembly }">
    <Found Context="routeData">
        <RouteView RouteData="@routeData" DefaultLayout="@typeof(Components.Layout.MainLayout)" />
        <FocusOnNavigate RouteData="@routeData" Selector="h1" />
    </Found>
</Router>

MauiBlazorWeb.Web プロジェクトの Program.cs ファイル内で次の AddAdditionalAssemblies 呼び出しによって MauiBlazorWeb.Shared.Client プロジェクト アセンブリを追加します (その _Imports ファイルを使います):

app.MapRazorComponents<App>()    
    .AddInteractiveWebAssemblyRenderMode()
    .AddAdditionalAssemblies(typeof(MauiBlazorWeb.Shared._Imports).Assembly)
    .AddAdditionalAssemblies(typeof(MauiBlazorWeb.Shared.Client._Imports).Assembly); 

.Shared.Client RCL に追加される、次の InteractiveRenderSettings クラスを追加します。 このクラスのプロパティは、サーバーベースのコンポーネントについてコンポーネントのレンダリング モードを設定するために使われます。

MAUI プロジェクトは既定では対話形式であるため、MAUI プロジェクト内のプロジェクト レベルでは、InteractiveRenderSettings.ConfigureBlazorHybridRenderModes を呼び出す以外のアクションは実行されません。

Web クライアント上の Blazor Web App の場合、それらのプロパティ値は RenderMode から割り当てられます。 MAUI プロジェクトのネイティブ クライアントの場合にコンポーネントが BlazorWebView に読み込まれると、レンダリング モードは割り当て解除 (null) されます。これは、ConfigureBlazorHybridRenderModes が呼び出されたときに MAUI プロジェクトによって明示的にレンダリング モードのプロパティが null に設定されるためです。

InteractiveRenderSettings.cs (.Shared.Client RCL):

using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Web;

namespace MauiBlazorWeb.Shared;

public static class InteractiveRenderSettings
{
    public static IComponentRenderMode? InteractiveServer { get; set; } = 
        RenderMode.InteractiveServer;
    public static IComponentRenderMode? InteractiveAuto { get; set; } = 
        RenderMode.InteractiveAuto;
    public static IComponentRenderMode? InteractiveWebAssembly { get; set; } = 
        RenderMode.InteractiveWebAssembly;

    public static void ConfigureBlazorHybridRenderModes()
    {
        InteractiveServer = null;
        InteractiveAuto = null;
        InteractiveWebAssembly = null;
    }
}

InteractiveRenderSettings クラスの少し異なるバージョンが .Shared RCL に追加されます。 .Shared RCL に追加されたクラスで、.Shared.Client RCL の InteractiveRenderSettings.ConfigureBlazorHybridRenderModes が呼び出されます。 これにより、MAUI クライアントでレンダリングされる WebAssembly コンポーネントのレンダリング モードが必ず割り当て解除 (null) されます。これは、それらがネイティブ クライアントで既定では対話形式であるためです。

InteractiveRenderSettings.cs (.Shared RCL):

using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Web;

namespace MauiBlazorWeb.Shared
{
    public static class InteractiveRenderSettings
    {
        public static IComponentRenderMode? InteractiveServer { get; set; } = 
            RenderMode.InteractiveServer;
        public static IComponentRenderMode? InteractiveAuto { get; set; } = 
            RenderMode.InteractiveAuto;
        public static IComponentRenderMode? InteractiveWebAssembly { get; set; } = 
            RenderMode.InteractiveWebAssembly;

        public static void ConfigureBlazorHybridRenderModes()
        {
            InteractiveServer = null;
            InteractiveAuto = null;
            InteractiveWebAssembly = null;
            MauiBlazorWeb.Shared.Client.InteractiveRenderSettings
                .ConfigureBlazorHybridRenderModes();
        }
    }
}

MauiProgram.csMauiProgram.CreateMauiAppで、ConfigureBlazorHybridRenderModesを呼び出します:

InteractiveRenderSettings.ConfigureBlazorHybridRenderModes();

.Shared.Client RCL の _Imports.razor ファイル内で、@using static InteractiveRenderSettings を追加して InteractiveRenderSettings クラスのプロパティをコンポーネントで使えるようにします:

@using static InteractiveRenderSettings

Note

この RCL の InteractiveRenderSettings クラス プロパティによるレンダリング モードの割り当ては、一般的なスタンドアロン Blazor Web App とは異なります。 Blazor Web App では、レンダリング モードは、通常は Blazor Web App の _Import ファイル内の @using static Microsoft.AspNetCore.Components.Web.RenderMode ステートメントにより RenderMode で提供されます。

インターフェイスを使ってさまざまなデバイス実装をサポートする

次の例では、インターフェイスを使って Web アプリとネイティブ (MAUI) アプリにわたりさまざまな実装を呼び出す方法を示します。 次の例では、デバイスのフォーム ファクターを表示するコンポーネントを作成します。 ネイティブ アプリには MAUI 抽象化レイヤーを使い、Web アプリには実装を提供します。

Razor クラス ライブラリ (RCL) で、Interfaces フォルダーを作成し、次のコードを含む IFormFactor.cs という名前のファイルを追加します。

Interfaces/IFormFactor.cs:

namespace MauiBlazorWeb.Shared.Interfaces;

public interface IFormFactor
{
    public string GetFormFactor();
    public string GetPlatform();
}

この RCL の Components フォルダーに、次の DeviceFormFactor コンポーネントを追加します。

Components/Pages/DeviceFormFactor.razor:

@page "/device-form-factor"
@using MauiBlazorWeb.Shared.Interfaces
@inject IFormFactor FormFactor

<PageTitle>Form Factor</PageTitle>

<h1>Device Form Factor</h1>

<p>You are running on:</p>

<ul>
    <li>Form Factor: @factor</li>
    <li>Platform: @platform</li>
</ul>

<p>
    <em>This component is defined in the MauiBlazorWeb.Shared library.</em>
</p>

@code {
    private string factor => FormFactor.GetFormFactor();
    private string platform => FormFactor.GetPlatform();
}

この RCL で、DeviceFormFactor コンポーネントのエントリをナビゲーション メニューに追加します。

Components/Layout/NavMenu.razor:

<div class="nav-item px-3">
    <NavLink class="nav-link" href="device-form-factor">
        <span class="bi bi-list-nested-nav-menu" aria-hidden="true"></span> Form Factor
    </NavLink>
</div>

Web アプリとネイティブ アプリで実装を提供します。

Blazor Web App で、 Services という名前のフォルダーを追加します。 Services フォルダーに、次のコードを含む FormFactor.cs という名前ファイルを追加します。

Services/FormFactor.cs (Blazor Web App プロジェクト):

using MauiBlazorWeb.Shared.Interfaces;

namespace MauiBlazorWeb.Web.Services;

public class FormFactor : IFormFactor
{
    public string GetFormFactor()
    {
        return "Web";
    }
    public string GetPlatform()
    {
        return Environment.OSVersion.ToString();
    }
}

MAUI プロジェクトで、Services という名前のフォルダーを追加し、FormFactor.cs という名前のファイルを追加します。 MAUI 抽象化レイヤーは、すべてのネイティブ デバイス プラットフォームで動作するコードを記述するために使われます。

Services/FormFactor.cs (MAUI プロジェクト):

using MauiBlazorWeb.Shared.Interfaces;

namespace MauiBlazorWeb.Maui.Services;

public class FormFactor : IFormFactor
{
    public string GetFormFactor()
    {
        return DeviceInfo.Idiom.ToString();
    }
    public string GetPlatform()
    {
        return DeviceInfo.Platform.ToString() + " - " + DeviceInfo.VersionString;
    }
}

依存関係の挿入を使ってこれらのサービスの実装を取得します。

MAUI プロジェクトで、MauiProgram.cs ファイルを開き、そのファイルの先頭に次の using ステートメントを追加します:

using MauiBlazorWeb.Maui.Services;
using MauiBlazorWeb.Shared.Interfaces;

builder.Build() の呼び出しの直前に次のコードを追加して、この RCL で使われるデバイス固有サービスを追加します:

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

Blazor Web App で、Program ファイルを開き、そのファイルの先頭に次の using ステートメントを追加します:

using MauiBlazorWeb.Shared.Interfaces;
using MauiBlazorWeb.Web.Services;  

builder.Build() の呼び出しの直前に次のコードを追加して、この RCL で使われるデバイス固有サービスを追加します:

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

また、このソリューションで .Web.Client プロジェクトを介して WebAssembly をターゲットにする場合は、 .Web.Client プロジェクトでも上記の API の実装が必要です。

RCL でコンパイラのプリプロセッサ ディレクティブを使って、このアプリが実行されるデバイスに応じて、異なる UI を実装することもできます。 このシナリオでは、アプリで、MAUI アプリと同様に、RCL を複数ターゲットにする必要があります。 例については、BethMassi/BethTimeUntil GitHub リポジトリを参照してください。

その他のリソース