Xamarin.Forms共通プロジェクトから各プラットフォーム設定ファイルの読み込み

xamarin.formsでiOSとAndroidそれぞれに設定ファイルをおいておき、それをForms内で読み込んで使用したい時の処理。
設定ファイルはjsonファイルで、App.xaml.csで読み込むというシチュエーションをかく。

プラットフォームごとのjsonファイルの配置と読み込み

以下の様な設定ファイルを想定。(設定内容に特に意味はない)

{
    "Id": "fuga",
    "Number": 3
}

これをAndroidの場合はAssetsとして、iOSはBundleResourceとして配置する。
そして共有プロジェクトに以下のクラスを定義する。

using System;
namespace Hoge.Models
{
    public class AppConfig
    {
        public string AppId { get; set; }
        public int Number { get; set; }
    }
}

共有プロジェクトから設定ファイルを読み込む

Appクラスにstatic変数でAppConfigを保持する様にする。なのでApp.xaml.csには以下の様に書いておく。

    private static AppConfig appConfig;
    public static AppConfig AppConfig
    {
        get
        {
            if (appConfig == null)
            {
                string text = DependencyService.Get<IAppConfig>().Get();
                appConfig = JsonConvert.DeserializeObject<AppConfig>(text);
            }
            return appConfig;
        }
    }

この時、DependencyService.Get().Get()によってそれぞれのプラットフォーム内にある設定jsonファイルを読み込むことになる。

ファイル読み込みクラスをインジェクション

共通プロジェクトに以下のインターフェイスを定義する。AppConfigファイルを読み込んで文字列で返すだけの定義である。

public interface IAppConfig 
{ 
    string Get();
}

そしてAndroidプロジェクトに以下を追加

[assembly: Dependency(typeof(AppConfig))]
namespace Hoge.Droid
{
    public class AppConfig : IAppConfig
    {
        public string Get()
        {
            AssetManager assets = Forms.Context.Assets;
            string content;
            using (StreamReader sr = new StreamReader(assets.Open("config.json")))
            {
                content = sr.ReadToEnd();
            }
            return content;
        }
    }
}

また、iosプロジェクトに以下を追加。

[assembly: Dependency(typeof(AppConfig))]
namespace Hoge.iOS
{
    public class AppConfig : IAppConfig
    {
        public string Get()
        {
            string path = Path.Combine(NSBundle.MainBundle.BundlePath, "config.json");
            return File.ReadAllText(path);
        }
    }
}

これでそれぞれの環境のconfig.jsonを読み込んで、Appクラスのstatic変数に確保でき、どこからでも使用できる。
ただ、この様に設定ファイルをjsonファイルで指定するメリットはないかもしれないが。