XAP をオンデマンドで読み込みには

Silverlight 4ベータSDKには、Managed Extensibility Framework(MEF)が含まれています。MEFを簡単に説明するとすれば、Composite Application を作成するためのフレームワークで、最新のモノはCodePlexで公開されています。このMEFとSilverlight Toolkitに含まれるSystem.ComponentModel.Coposition.Packaging.Toolkit.dllを組み合わせると、別のXAPをダウンロードして複合化(Composition)アプリケーションに仕上げることができます。このPackaging.Toolkitに含まれるPackageクラスを使って、自分で外部のXAPを読み込む方法をご紹介します。外部のパッケージを読み込むには、以下のようなコードを記述します。

 

 Package package;
// イベントハンドラ
private void btnDownload_Click(object sender,
                               RoutedEventArgs e)
{
    Uri uri = new Uri("ExternalXap1.xap", UriKind.Relative);
    Package.DownloadPackageAsync(uri,
                 (args, p) => package = p );
}

 

PackageクラスのDownloadPackageAsyncメソッド呼び出せば、ラムダ式に記述したようにpackage変数にダウンロードしたXAPに関する情報が格納されます。格納されたPackageクラスのインスタンスには、以下のようなプロパティがあります。

  • Uriプロパティ:指定したXAPのUriです。
  • Assemblies:XAPに含まれるAppManifest.xamlのAssemblyPartで定義されているアセンブリをインスタンス化したコレクションです。

Packageクラスのインスタンスが手に入れば、クラスのインスタンスを作成するには以下のようにします。

 

 foreach (var asm in package.Assemblies)
{
    // 該当するアセンブリを見つけた場合
    object obj = asm.CreateInstance("クラス名");
    // 作成したインスタンスを使って何かの処理を行います
}

このPackageクラスのDownloadPackageAsyncメソッドを調べると以下のようなことを行っているのを理解することができます。

  • WebClientクラスを使ってXAPの読み込み。
  • XAPのStreamからStreamResourceInfoを作成。
  • StreamResourceInfoからAppManifest.xamlを読み込み。
  • マニフェストのAssemblyPartのSourceを使ってAssemblyPartインスタンスの作成。
  • Application.GetResourceStreamを使ってアセンブリの読み込み(AssemblyPart.Load)。
  • アセンブリのコレクションをPackageクラスのインスタンスに格納して、コールバック。

この動作から理解できることは、Silverlight 2で提供されたAPIだけで動的なXAPの読み込みというのが実現できるということです。また、Silverlight 4 ベータにおいて XAPの動的な読み込みに対応したAPIが提供されるのではなく、現状ではSilverlight Toolsの一部として提供されるということです。

追記:Silverlight2で動的にXAPを読み込むというチュートリアルがSilverlight.netで公開されていました。Loading Dynaic XAPs and Assemblies というものです。ビデオとサンプルコードが公開されています。