ぴーさんログ

だいたいXamarin.Formsのブログ

MAUI移行時のDependencyServiceの対処

Xamarin.FormsアプリをMAUIへ移行する際に遭遇した問題から一つ。

問題
DependencyService.Get<T>()でインタンスを取得できなくなる。

解決方法
型の登録方法を変更し、DependentyAttributeで自動登録する方法から、明示的な手動登録に変更する。

解説

MAUIへ移行すると DependencyService.Get<T>() した際にインスタンスを取得できなくなると思います。

型の自動登録は、DependencyService.Get<T>()した際にDependencyServiceが未初期化なら、AssemblyからDepenedency属性のついた収集して初期化するという実装になっています。

しかし、MAUIではブートストラップ処理中にDependencyServiceを初期化済みとマークするため自動登録が働くなっています。 このため、従来の処理を移植すると未登録の型を要求することになりインスタンスが取得できなくなります。

おそらくMAUI標準のDependency Injectionを利用して欲しいという意図とパフォーマンス上の理由でこのような扱いになっているのだと思います。 (依存関係の挿入 | Microsoft Learn)

対策としては、こんな感じの型登録処理を用意して MauiProgram.CreateMauiApp() の際に呼ぶと良いでしょう。

static void SetupDependencyService()
{
#if ANDROID
    DependencyService.Register<IService, MyApp.AndroidServiceImpl>();
#elif IOS
    DependencyService.Register<IService, MyApp.iOSServiceImpl>();
#endif
}

余談
理屈としては UseMauiApp<T>() より先に DependencyService.Get<T>() すると型の自動登録が走るので、そういう解決方法もアリかも?

参考

DependencyService初期化済みとする部分

maui/src/Controls/src/Xaml/Hosting/AppHostBuilderExtensions.cs at f04c5aff095525ab99417d68796849962a4c4903 · dotnet/maui

DependencyAttributeから型を自動登録する部分

maui/src/Controls/src/Core/DependencyService.cs at f04c5aff095525ab99417d68796849962a4c4903 · dotnet/maui