Xamarin.FormsでUnity.Configurationしてみた。
はじめに
引越しつらい現実逃避で記事書きました/(^o^)\
Unity
ゲーム作る方のじゃなくてDIとかする方のUnityのお話です。
現在、開発が止まって放置されているらしくて今後メンテの期待薄なので今更Unityのネタを書こうか迷ったんですがとりあえず書いてみることにしました。
UnityContainerの拡張メソッドにLoadConfigurationってあるのご存知ですか?
app.Configとかweb.configにContainerへのレジストを記述してLoadConfigurationすると、その設定どおりにContainerに登録を行ってくれます。
これ.NET45なプロジェクトだと使えるんだけどXamarinとかPCLでは使えないんです。
どうしてかというとSystem.Cofigurationに依存している拡張なのでSystem.Configurationが基本的に使えない環境を外してるんですね。
それを今回はPCLプロジェクトでもある程度使ってみるサンプルを作りました。
Xamarin.Formsへの対応
Windows8.1とかは対象外です。今回はAndroidで動作確認しています。たぶんiOSでも動くはずです。Macを既に梱包しちゃったので試せません。
UWPは頑張れば対応できそうなんですが今回は見送りました。
解説
プロジェクトの作成
まずはプロジェクトの作成を行います。
Xamarin.FormsプロジェクトをPCLにて作成してください。
PCLを.NET Standardに対応
こちらの記事を参考にPCLプロジェクトを.NET Standardに対応させてください。
.NET Standardのバージョンは1.5としてください。
Unity.Configurationの追加
UnityのConfiguration機能をPCLで使用するためにUnity,Configurationというパッケージを使用します。
ソリューションのnugetマネージャーを開いてUnity.Configurationというパッケージを追加します。
Pre版ですので「プレリリースを含める」にチェックを入れて検索してください。
テスト動作用のインターフェースと実装クラスを追加します。
めんどくさいのでこんな感じで。
namespace App4 { public interface IHogeHoge { string GetHoge(); string GetHogeHoge(); } public class HogeHogeA : IHogeHoge { public string GetHoge() => "HogeA"; public string GetHogeHoge()=> "HogeHogeA"; } }
PCLにconfigファイルを追加します。
unity.configという名前でconfigファイルを追加します。
ビルドアクションは埋込リソースにしてください。
ファイルの中はこんな感じで。
<unity xmlns="http://schemas.microsoft.com/practices/2010/unity"> <!-- Define Assemblies--> <assembly name="App4" /> <!-- End Assemblies--> <!-- Define Namespaces--> <namespace name="App4" /> <!-- End Namespaces--> <container> <register type="App4.IHogeHoge, App4" mapTo="App4.HogeHogeA, App4" /> </container> </unity>
他にも色々とできますがUnity.Configurationの使い方は別途ぐぐってください。
ConfigurationSectionReaderクラスを追加する
c# - How to Read a Configuration Section from XML in a Database? - Stack Overflow
こちらを参考にしました(コピペ)
こんな感じのクラスを追加しておきます。
public class ConfigurationSectionReader<T> where T : ConfigurationSection, new() { public T GetSection(string sectionXml) { T section = new T(); using (StringReader stringReader = new StringReader(sectionXml)) using (XmlReader reader = XmlReader.Create(stringReader, new XmlReaderSettings() { CloseInput = true })) { reader.Read(); section.GetType().GetMethod("DeserializeElement", BindingFlags.NonPublic | BindingFlags.Instance).Invoke(section, new object[] { reader, true }); } return section; } }
LoadConfigurationする
appクラスにてcontainerを作ってLoadConfigurationします。
public App() { InitializeComponent(); IUnityContainer container = null; var assembly = typeof(App).GetTypeInfo().Assembly; using (var stream = assembly.GetManifestResourceStream("App4.unity.config")) { using (TextReader reader = new StreamReader(stream)) { var configtext = reader.ReadToEnd(); var configreader = new ConfigurationSectionReader<UnityConfigurationSection>(); var sect = configreader.GetSection(configtext); container = new UnityContainer(); container.LoadConfiguration(sect); } } MainPage = new App4.MainPage(container.Resolve<IHogeHoge>().GetHogeHoge()); }
結果
おわりに
Unity.Configurationライブラリに関しては余裕ができたらもう少し真面目に取り組んでみようかと思います。
ではでは( `ー´)ノ