shuhelohelo’s blog

Xamarin.Forms多めです.

BlazorでのDIコンテナの使い方

BlazorというかASP.NETにはDIコンテナの機能が提供されています。

DIコンテナの機能を使うことで、Razorページの中、または他のクラスの中で使用するインスタンスの生成を任せることができます。

Razorページ内では

  1. Startup.cs内のConfigureServicesメソッドの中で使用するオブジェクトを登録
  2. @injectで使用するオブジェクトを指定する

例えば、以下のようなクラスAがあるとします。 これは「Hello」という文字列を返すGreetingメソッドを持っています。

    public class A
    {
        public string Greeting() => "Hello";
    }

このクラスをRazorページ内で使う場合、DIを使わないのであれば以下のようになるでしょう。

@page "/"

<h1>Hello, world!</h1>

Welcome to your new app.

<SurveyPrompt Title="How is Blazor working for you?" />

@Greeting()

@functions{
    A a = new A();

    string Greeting()
    {
        return a.Greeting();
    }
}

例がアホですが、Razorページ内でクラスAインスタンスを生成する必要があるということです。

これに対してDIコンテナを使う場合は以下のようになります。

まず、Startup.csでオブジェクトを登録します。ここではクラスAをSingletonとして登録します。

using Microsoft.AspNetCore.Components.Builder;
using Microsoft.Extensions.DependencyInjection;

namespace WebApplication5
{
    public class Startup
    {
        public void ConfigureServices(IServiceCollection services)
        {
            //クラスAのオブジェクトを登録
            services.AddSingleton<A>();
        }

        public void Configure(IComponentsApplicationBuilder app)
        {
            app.AddComponent<App>("app");
        }
    }
}

そしてRazorページ側で@injectディレクティブを使ってクラスAインスタンスを使えるようにします。

@page "/"
@* クラスAのインスタンスを注入 *@
@inject A a  

<h1>Hello, world!</h1>

Welcome to your new app.

<SurveyPrompt Title="How is Blazor working for you?" />

@*クラスAのインスタンスを使える*@
@a.Greeting()

クラスAのインスタンスを直接指定しましたが、インターフェス経由でインスタンスを注入することもできます。

その場合は、オブジェクトの登録で以下のようにします。

            //クラスAのオブジェクトを登録
            services.AddSingleton<IA, A>();

そして、Razorページでは以下のようにします。

@inject IA a  

他のクラス内で使用する場合

例えば、Razorページのロジック部分をコードビハインドとして別クラスに切り分けた場合についてです。

オブジェクトの登録については変わりませんが、Razorページとコードビハインド側は以下のようになります。

@page "/"
@inherits WebApplication5.Pages.IndexBehind

<h1>Hello, world!</h1>

Welcome to your new app.

<SurveyPrompt Title="How is Blazor working for you?" />

@*クラスAのインスタンスを使える*@
@a.Greeting()
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Components;

namespace WebApplication5.Pages
{
    public class IndexBehind : ComponentBase
    {
        //注入先のプロパティ(プロパティインジェクション)
        [Inject]
        public A a { get; set; }
    }
}

Razorページとそのコードビハインドとなるクラスの間の紐付けについては別の記事に書きました。

重要なのはコードビハインド側でクラスAインスタンスの注入先となるプロパティにInject属性をつける、ということです。

これで自動的にクラスAインスタンスがプロパティaに注入され、Razorページでプロパティa経由で使用することができます。