SilverlihtアプリのWebサービスコール設定をXAPから外出しする(その2)

SilverlihtアプリのWebサービスコール設定をXAPから外出しする(その1)の続きです。

アジェンダ

  • ServiceClientBuilderクラス
  • ServiceClientBuilderクラス
  • テスト用ソリューションの構築
  • ServiceClientBuilderを初期化
  • サービスクライアントの生成テスト

ServiceClientBuilderクラス

ジェネリック型のServiceClientBuilderクラスの親クラスです。このクラスは、staticプロパティでServiceConfigを保持します。

public class ServiceClientBuilder
{
    public static ServiceConfig ServiceConfig { get; set; }
}

ServiceClientBuilderクラス

ServiceClientBuilderクラスは、実際にサービスクライアントを生成する機能を提供します。Tの制約は、サービスクライアントがインターフェイスのICommunicationObjectとなります。本来ならば、より直接的なClientBaseクラスを制約として持つべきなのですが、ClientBaseジェネリック型なため、ServiceClientBuilderのT指定が面倒になってしまいます。そのため、今回はICommunicationObject型制約としました。

public class ServiceClientBuilder<T> : ServiceClientBuilder
    where T : class, ICommunicationObject
{
    private string serviceID;

    public ServiceClientBuilder(string serviceID)
    {
        this.serviceID = serviceID;
    }

    /// <summary>サービスクライアントを生成する。</summary>
    /// <returns></returns>
    public T Build()
    {
        // ServiceInfoを親クラスのstaticプロパティから取得する。
        ServiceInfo info = ServiceConfig.GetServiceInfo(this.serviceID);

        // サービスクライアントのコンストラクタに渡す値を取得する。
        Binding binding = info.Binding;
        EndpointAddress remoteAddress = info.EndpointAddress;

        // サービスクライアントをリフレクションで生成する。
        Type type = typeof(T);
        T client = Activator.CreateInstance(type, binding, remoteAddress) as T;

        return client;
    }        
}

以上で、クラスの定義が完了しました。

テスト用ソリューションの構築

それでは、実際にサービスクライアントビルダーを使用してみます。下記のようなソリューションを作りました。

ServiceClientBuilderを初期化

App.xaml.csで、RootVisualにMainPageを登録する前にServiceClientBuilderを初期化する処理を記述します。

//// App.xaml.cs

private void Application_Startup(object sender, StartupEventArgs e)
{
    // Client.config.xmlをダウンロードする。
    Uri clientConfigUri = new Uri("Client.config.xml", UriKind.Relative);
    WebClient webClient = new WebClient();
    webClient.DownloadStringCompleted += new DownloadStringCompletedEventHandler(WebClient_DownloadStringCompleted);
    webClient.DownloadStringAsync(clientConfigUri);
}

private void WebClient_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
{
    if (e.Cancelled == false && e.Error == null)
    {
        // XMLファイルからServiceClientBuilderを初期化する
        bool isSuccess = this.InitServiceClientBuilder(e.Result);
        if (isSuccess)
        {
            // ServiceClientBuilderの初期化が成功したならば、MainPageを表示する。
            this.RootVisual = new MainPage();
        }
    }
    else
    {
        MessageBox.Show(
            "設定ファイルのダウンロードに失敗しました。"
            + Environment.NewLine
            + "しばらくたった後、お試しください。");
    }
}

private bool InitServiceClientBuilder(string configStr)
{
    try
    {
        // パーサでServiceConfigを生成し、ServiceClientBuilderを初期化する。
        ServiceClientParser parser = new ServiceClientParser();
        ServiceClientBuilder.ServiceConfig = parser.Parse(configStr);
        return true;
    }
    catch (Exception)
    {
        MessageBox.Show(
            "設定ファイルの解釈に失敗しました。"
            + Environment.NewLine
            + "システム管理者にご連絡ください。");
        return false;
    }
}

サービスクライアントの生成テスト

サービスビルダーからサービスクライアントを生成するサンプルを示します。

// サービスクライアントを生成する。
// serviceIDは、XMLのservice要素のid属性の値を指定する。
string serviceID = "TestService1";
ServiceClientBuilder<TestService1Client> builder = new ServiceClientBuilder<TestService1Client>(serviceID);
TestService1Client client = builder.Build();

// コンプリートイベントハンドラの登録
client.DoWorkCompleted += (s, e) =>
{
    MessageBox.Show(e.Result);
};

// サービスをコールする。
client.DoWorkAsync("Test");