ViewMakerにみるMVVMの実装(4)

今回はViewMakerで利用しているサービスについて説明します。

ServiceLocatorによりサービス切り替え

ViewMakerではViewLayoutの生成や永続化、XAMLの生成などの処理をサービスとして定義・実装しています。これらのサービスはMEFを使ってIoCの仕組みで入れ替え可能にしています。
IoCの仕組みとしてはDIが一般的ですが、ViewMakerではServiceLocatorの仕組みを利用しています。サービスを入れ替える意味ではServiceLocatorの方が自然だと考えているからです。ただ今回サービス以外についても同じ仕組みを使っていますので個人的な好みといった方が良いかもしれませんね。

ViewMakerで定義しているサービスには以下のものがあります。

・IViewContentGenerateService
・IViewGenerateService
・IViewLayoutGenerator
・IViewLayoutPersistenceService
・IXamlGenerator

最初の2つはViewModelからViewのインスタンスを生成するトップレベルのサービスです。内部的にはよりプリミティブなIViewLayoutGeneratorやIXamlGeneratorを利用しています。残りの3つはそれぞれプリミティブなサービスです。IViewLayoutGeneratorはViewModelから論理的なViewレイアウトを生成するサービスです。
IViewLayoutPersistenceServiceはViewレイアウトを保存するサービスで、既定ではSilverlightは分離ストレージ、WPFはカレントディレクトリにタイプ名.xmlの形式でファイル保存します。したがって、レイアウト情報をDBに保存したいような場合にはこのサービスを置き換えることで対応することができます。
最後はViewレイアウトをXamlに変換するサービスです。生成するテンプレート切り替えなどしたい場合はこのサービスを置き換えます。

メタ情報ベースの生成をより柔軟にするProviderパターン

上記のインフラ的なサービスではありませんが、IViewLayoutGeneratorProviderというインタフェースがあります。これをViewModelに実装すると自動生成されるレイアウトを自分自身で制御することができます。たとえば以下のように使います。TabControlを使った画面を生成する例になっています

        ViewLayoutItem IViewLayoutGeneratorProvider.Generate()
        {
            var detailLayout = ServiceLocator.GetService<IViewLayoutGenerator>().Generate(typeof(TestViewModel), LayoutGenerateFlag.LayoutData);
            if (detailLayout != null) return detailLayout;
            detailLayout = ServiceLocator.GetService<IViewLayoutGenerator>().Generate(typeof(TestViewModel), LayoutGenerateFlag.TypeInfo);

            var tabcontrol = detailLayout.AddChild("AddressTab", ViewControlType.TabControl);
            var a1 = detailLayout.FindChild("AddressXMainPanel");
            var a2 = detailLayout.FindChild("AddressYMainPanel");
            a1.Remove();
            a2.Remove();
            tabcontrol.AddChild(a1);
            tabcontrol.AddChild(a2);
            return detailLayout;
        }

メタ情報を使った自動生成は簡単に利用できますが柔軟さがありません。これをProvider用インタフェースで補完するという考え方です。XmlSerialzerにたいするIXmlSerializableのようなもので、自動生成パターンでの定番の仕組みです。あと自動生成の仕組みを作成する場合Expression Builderのパターンも組み合わせてよく利用します。今回はViewLayoutBuilderで実装しており、メソッドチェーンでViewレイアウトを作成できるようにしています。

まとめ

ViewMakerのほとんどの機能はサービス化されて入れ替え可能になっている。
メタ情報による自動生成を補完する仕組みが用意されており簡便さと柔軟さのバランスをとっている。