CodeZine(コードジン)

特集ページ一覧

.NET Frameworkの最新技術とSilverlightとの連携

Silverlight 2で作成する業務アプリケーション入門(4)

  • LINEで送る
  • このエントリーをはてなブックマークに追加

 Silverlightと言うとリッチなユーザーインターフェイスや、アニメーションと言ったインタラクティブな要素ばかり注目されがちですが、 Silverlight 2からは、ジェネリックやLINQ、スレッドといった.NET Frameworkの機能がサポートされました。今回はSilverlightで使用できる.NET Frameworkの最新技術とSilverlightの連携について触れていきたいと思います。

はじめに

 Silverlightと言うとリッチなユーザーインターフェイスや、アニメーションと言ったインタラクティブな要素ばかり注目されがちですが、Silverlight 2(以下 Silverlight)からは、ジェネリックやLINQ、スレッドといった.NET Frameworkの機能がサポートされました。これによりSilverlightでは.NET Frameworkのライブラリを使用し、効率的に業務アプリケーションを構築できるようになったという点も忘れてはいけません。

 今回はSilverlightで使用できる.NET Frameworkの最新技術とSilverlightの連携について触れていきたいと思います。

対象読者

 Silverlight開発初心者。

Silverlight概要の復習

 最初にSilverlightの概要について振り返っておきましょう。Silverlightは本連載の1回目でも触れたように、図1のアーキテクチャで構成されています。

図1:Silverlight 2のアーキテクチャ
図1:Silverlight 2のアーキテクチャ

 Silverlightは.NET Framework 3.5のサブセットとして実装されています。つまり、コレクションの検索や、サーバー側アプリケーションとの連携、.NET Frameworkと同じ型システム、ガーベッジコレクタといった.NET Frameworkの共通基盤をSilverlightでも利用できるようになったということです。

 また、分離ストレージを使ったユーザー情報の保存、スレッドを使った非同期プログラミング、HTML DOMとの連携といったインターネットアプリケーションの構築を助けるためにの機能が豊富に提供されているのもSilverlightの特徴の一つです。

 Silverlightが提供している機能の概要を表1に示します。

表1 Silverlightで提供している機能の概要
機能 説明
データ操作 LINQによる、多種多様なデータソースへのアクセスを行う機能を提供
基本クラスライブラリ 文字列処理、コレクション、国際化、などのクラスライブラリを提供
WCF(Windows Communication Foundation)との連携 リモートサービスにアクセスするため、各種データ通信プロトコルをサポート
DLR(動的言語ランタイム) Silverlight上で、JScriptやRuby、Pythonといった動的言語の動作をサポート
分離ストレージ ユーザー個別の情報をユーザーのローカルコンピュータ内に保存する機能を提供
非同期プログラミング BackgroundWorkerクラスを提供し、簡単なスレッドプログラミングをサポート
HTML DOMとの連携 HTML DOMとSilverlightの相互運用をサポート
シリアル化 JSONおよびXMLのCLRオブジェクトへのシリアル化をサポート

複数プログラミング言語のサポート

 今までクライアントサイドのプログラミングと言えば、HTMLであればJavaScript、FlashであればActionScriptを使ってプログラミングを行っていました。この2つの言語は習得にそれほど時間がかかるわけではありませんが、普段プログラミングを行っているC#やVisual Basicなどとは違った動的に型付けされた言語であり、静的に型付けされた言語とは違うプログラミングが必要とされました。

 プログラミングのバグの中で最も発見が困難な類のバグは、型に基づいたバグだと筆者は考えています。例えば最初は整数型で宣言していた変数がプログラム中のコードにより、いつの間にか文字列型の変数に置き換わっていたため、計算結果がおかしくなってしまったり、本来はインスタンスが持っていないはずのメソッドを呼び出すコードを記述し、実行時に初めてエラーに気付くといった問題です。

リスト1 JavaScriptによるコーディングのバグ(JavaScript)
var total = 0;          // total の値は 0 (int)
total = total + "1";    // total の値は 01 (string)

var s = "abc";
s.method1();            // 実装していないメソッドの呼び出し

 静的言語では、これらのバグはコンパイル時にチェックし、インスタンス同士の型変換が可能であるか、インスタンスは指定されたメソッドを持っているかなどをコンパイル時に発見することが可能になっています。特に業務アプリケーションのように大人数で作成するアプリケーションではプログラマーの力量もバラバラなことが多く、コンパイル時にチェックできるものはできるだけコンパイラーによって検知できる仕組みがある言語が望まれていました。

 しかし、動的言語が業務アプリケーション開発に向いていないと言っているわけではありません。確かに静的な型チェックがないためコーディングの際に注意が必要ですが、本来プログラムは目的を記述するためのものであり、型情報はある意味ノイズであると考えることもできます。動的言語では型を動的に決定することでコーディング量を少なくし、簡潔にプログラミングすることが可能になります。

 Silverlightでは後述するDLRを使うことで、CLR上で動作する動的言語の基盤もサポートしています。現在のところSilverlightでは、JScriptやIronRuby、IronPythonといった言語がサポートされています。

Silverlightの基本機能

 今回は、図1中の上部にある.NET Framework for Silverlightの部分を掘り下げて、Silverlightがどのように業務アプリケーションで利用できるかを解説していきます。

Silverlightと.NET Framework

 Silverlightでは図1や表1で紹介したように、.NET Framework 2.0で登場したジェネリックや.NET Framework 3.5で登場したLINQといった.NET Frameworkの最新技術を使用してプログラミングを行うことができます。ここでは簡単に、業務アプリケーションで使用する上で役に立ちそうなSilverlightの基本機能について紹介します。

ジェネリック

 「ジェネリック」は.NET Framework 2.0で導入された機能で総称型とも呼ばれます。

 ジェネリックでは、型付けされたコレクションを簡単に利用できます。型付けされたコレクションを使うことで、予期しない型のインスタンスがコレクションを追加することができなくなるため、プログラムの堅牢性が向上し、不要なキャストが必要なくなるためコレクションの操作も高速になります。

 リスト2では、wingsUsersというWingsUser型のコレクションを作成し要素を追加していますが、偽WingsUserはstring型のインスタンスであるため、コレクションに追加することはできません。

リスト2 ジェネリックによるプログラミング(C#)
var wingsUsers = new List<WingsUser>{
    new WingsUser { Name = "山田" },
    new WingsUser { Name = "かるあ" },
};

wingsUsers.Add("偽WingsUser");    // コンパイルエラー

 wingsUserがどんな型のインスタンスでも受け入れるコレクションだったらどうなるでしょう。プログラムコードでは、要素の一つ一つに対し、それが想定している型のインスタンスかをチェックし、キャストしてからアクセスする必要があります。ジェネリックを使うことで想定していない動作防ぐことができプログラムの堅牢性が向上します。

スレッド

 ボタンがクリックされた際に、時間がかかる処理を行っているため、UIが操作を受け付けず固まったようなアプリケーションを見たことはありませんか? これはUIスレッドで時間のかかる処理を行っているため、UI側に処理が返却されないことが原因で起こる問題です。JavaScriptの場合、リスト3のようにsetTimeout関数を使って疑似的にスレッドを表現します。

リスト3 JavaScriptで疑似的にスレッド処理を行うコード(JavaScript)
function button1_Click() {
    setTimeout(重い処理, 1);
}

function 重い処理() {
    // 重い処理
}

 setTimeout関数は指定時間後に定義した処理を実行する関数です。この場合、1ミリ秒後に重い処理()を実行しますが、UIスレッド自体はbutton1_Clickメソッドを終了してUIに処理を戻しているため、重い処理()が別スレッドで動作しているように見えます。

 Silverlightでは.NET Frameworkのスレッドをサポートしているため、リスト4のようにBackgroundWorkerなどのクラスを使うことで簡単にスレッドに対応したアプリケーションを作成することができます。

リスト4 Silverlightのスレッド処理
private void Button_Click(object sender, RoutedEventArgs e)
{
    var 重い処理を行うスレッド = new BackgroundWorker();
    重い処理を行うスレッド.DoWork += 重い処理;
    重い処理を行うスレッド.RunWorkerAsync();

}

private void 重い処理(object sender, DoWorkEventArgs e)
{
    // 重い処理
}

 スレッドによるプログラミングではUI要素へのアクセスで注意が必要です。WindowsFormではUIスレッド以外のスレッドからUIの要素にアクセスすることは禁止されていました。Silverlightも同様に、UIスレッド以外からUIの要素にアクセスすると、UnauthorizedAccessException例外が発生します。

 WindowsFormアプリケーションでは、各コントロールに用意されているInvokeメソッドを使って非同期に各コントロールにアクセスしますが、SilverlightではコントロールはInvokeメソッドをサポートしていません。SilverlightでUIスレッド以外からUI要素にアクセスするためには、リスト5のようにScriptObjectが公開するDispatcherプロパティのBeginInvokeメソッドを使用してUI要素へアクセスします。

リスト5 Dispatcherクラスを使ったUI要素へのアクセス
private void 重い処理(object sender, DoWorkEventArgs e)
{
    // 重い処理

    // UI への書き込み
    Dispatcher.BeginInvoke(delegate()
    {
        result.Text = "重い処理終了";
    });
}

LINQ

 LINQ(Language INtegrated Query)は.NET Framework 3.5で導入された機能で言語統合クエリとも呼ばれています。LINQでは、オブジェクトやXMLといったコレクションに対して検索や更新、オブジェクトの付け替えを簡単に行える機能が提供されています。

 Silverlightはクライアント側の技術であるため、データベースに格納されたデータの表示、更新といった作業はサーバー側プログラムとの連携を行って実現する必要があります。このため、クライアント側にダウンロードしたデータの表示内容をカスタマイズしたり、キャッシュしたデータに対し再検索するといった機能が重要になります。

 LINQを使用することで、ダウンロードしたオブジェクトに対する検索や、データの表示内容の変更といった作業をシンプルにコーディングすることができるようになります。

 例えばリスト6では、GetUsersメソッドがサーバーからユーザーの一覧を取得するメソッドだったとして、その後のコードで、習得したデータに対して再検索を行っています。

リスト6 LINQ を使った再検索(C#)
var serviceResult = GetUsers();

// 検索結果の再検索、並び替え
var query1 = from user in serviceResult
            where user.Name.StartsWith("か")
            orderby user.Name ascending
            select user;

 データグリッドを使った検索画面や、更新処理などのリストデータを扱うシナリオを考えた場合、サーバーとの通信で取得したデータに対し、検索や更新を行うことでパフォーマンスの向上を図ることができます。

 実際のサーバーサイドアプリケーションとの連携に関しては次回以降の連載で詳しく解説します。

JSON形式のデータをサポート

 JSON(JavaScript Object Notation)はJavaScriptにおけるデータの表現方法の一つです。例えば先ほど例に挙げたWingsUserの一覧をJSONではリスト7のように表すことができます。

リスト7 JSONによる表現(JavaScript)
var members = [
  { name; '山田'},
  { name: 'かるあ' },
];

 JSONでは、配列を[]で、オブジェクトを{}でそれぞれ定義します。

 この場合、members変数にはnameというプロパティを持つオブジェクトの配列が格納されます。このようにJSONを使うことでシンプルな構文でデータ表現が行えるため、この頃ではXMLの代わりにJSONによるデータ表現を使ったWebServiceも増えています。

 SilverlightではJSON形式のデータをCLR型にマッピングすることが可能です。

 リスト8では、JSON形式で宣言されたオブジェクトをデシリアライズしてWingsUsreの配列にマッピングしています。

リスト8 JSON データのマッピング
List<WingsUser> GetUser()
{
    var textReader = new System.IO.StringReader(
        "[ { name: 'かるあ' }, { name : 'やまだ' } ]"
    );
    var jsonData = (JsonArray)JsonArray.Load(textReader);
    var query = from member in jsonData
                select new WingsUser { Name = member["name"] };
    return query.ToList();
}

 JsonArray.Loadメソッドは、引数に渡されたストリームからJSON形式のデータをロードし、CLRの型にマッピングします。以降のプログラムではロードされたデータに対し、ディクショナリからデータを取り出してプログラミングを行います。

 Loadメソッドで取得したデータに対しては、"name"などの文字列を使ってデータにアクセスする必要があるため、キーの指定間違いなどで実行時エラーが発生する可能性があります。JSONを使ったプログラミングでは、直接JsonArray型やJsonObject型に対してプログラミングをするのではなく、リスト8のように一度.NETのクラスにマッピングしてからデータにアクセスすることで、実行時エラーの範囲を小さくすることができます。

SilverlightとDLR(Dynamic Language Runtime)

 SilverlightではDLR上でPythonやRuby、JScriptといった言語での開発をサポートしています。本項では、SilverlightにおけるDLRが業務アプリケーションにどのように役立つのかを調べていきたいと思います。

DLRとは

 DLR(Dynamic Language Runtime)とは、.NET Frameworkで動的言語を動作させるための実行基盤です。DLRによって、各動的言語間の型を一貫して提供することで、動的言語間やC#やVisual Basicと言ったCLR(Common Language Runtime)の言語間の会話を可能とします。現在サポートされている動的言語はIronPython、IronRuby、Managed JScriptの3つですが、DLRの登場で.NET Framework上で動的言語を作りやすくする環境が整備されたということになります。

SilverlightとDLRの関係

 DLRは図2のように、.NET Frameworkや.NET Framework for Silverlightの上に実装され、コンソールアプリケーションやASP.NET、Silverlightといった環境にホストされます。

図2:DLRの概要
図2:DLRの概要

 つまり、DLR上に構築された動的言語を使用すれば、コンソールアプリケーション、ASP.NET、Silverlightといったアプリケーションで動的言語を使用したり、C#やVisual Basicといった言語から、動的言語で実装された機能を呼び出すことが可能になるのです。

 また、Silverlightでは、後述するHTML DOMとの統合機能によってSilverlightからクライアントのHTMLを操作することが可能なため、JavaScriptの代わりに動的言語を使用してHTMLの操作を行うことも可能になっています。

SilverlightでDLR対応言語を使用するためには

 SilverlightでDLRを使用するためには、CodePlexで提供されているSilverlight Dynamic Languages SDKを使ってプログラミングを行う必要があります。

 このSDKには、SilverlightでIronPythonやIronRuby、JScriptといった言語を動作させるためのdllと、各言語でSilverlightアプリケーションを作成するためのテンプレート、xapファイルの作成コマンドといった物が含まれます。

 使い方については、同梱されているReadme.txtを確認してください。

動的言語を使うメリット

 .NET Framework上で動的言語を使用できるとして、業務アプリケーションを開発する際のメリットはどのような物があるでしょうか。

 筆者は動的言語を使うことで次のようなメリットがあると考えています。

  • 動的言語の開発経験をそのままSilverlightで使用することが可能
  • 動的言語を「のりしろ」的な役割で使用することで柔軟な対応が可能

 1つ目の利点については説明は不要でしょう。DLRでは、現在正式にサポートされているIronRubyやIronPython、JScriptに加えLispやScalaといった動的言語の開発も進められています。SilverlightとDLRの組み合わせを使用することで、開発者は好きな言語を選んでアプリケーションの開発が可能となります。

 2つ目の利点については、少し説明が必要でしょうか。

 DLR上に作成されたアプリケーションは、CLRから動的に呼び出して実行することができます。つまり、C#やVisual Basicといった言語からIronPythonやIronRubyで作成されたスクリプトを読み出して実行することができるということです。

 この特性を利用して、ユーザーから頻繁に仕様変更が予想される部分や、手軽に変更を行いたい部分を動的言語で実装し、C#やVisual Basicから呼び出します。動的言語を動的な部分と静的な部分をつなぐ「のりしろ」として使用するのです。

 リスト9はC#から動的にPythonのコードを実行している例です。

リスト9 C#からのPythonコードの動的実行
var pythonCode = "1 + 2";

// 1.動的言語の設定
var languageSetup = new LanguageSetup(
    "IronPython.Runtime.PythonContext, IronPython, " +
    "Version=2.0.5.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35",
    "IronPython 2.0",
    new string[] { "IronPython", "Python", "py" },
    new string[] { ".py" }
    );
var scriptSetup = new ScriptRuntimeSetup();
scriptSetup.DebugMode = true;
scriptSetup.LanguageSetups.Add(languageSetup);

// 2.動的言語のエンジンを取得
var runtime = new ScriptRuntime(scriptSetup);
var scope = runtime.CreateScope();
var engine = runtime.GetEngine("py");

// 3.コードの実行
var sum = engine.Execute(pythonCode, scope);

 動的言語をC#などから呼び出す場合は、次の手順で動的言語を読み込む必要があります。

  1. 動的言語の設定
  2. 動的言語のエンジンを取得
  3. コードの実行

 例えばコード中の pythonCode は IronPython のソースコードを格納した文字列です。プログラム中でソースコードをサーバーからダウンロードして実行することで、C# や Visual Basic で記述された既存のSilverlightプログラムをコンパイルすることなく動作を変更することもできますし、Excelの計算式のようにユーザーにプログラムの動作を定義してもらうといった使い方もできます。

 C#やVisual Basicで業務アプリケーションを作成している場合は、C#やVisual Basicといった強い型付け言語をメインにプログラムを作成し、動的に変更したい一部を動的言語で作成するというシナリオが思い浮かびます。

SilverlightとHTML DOMの連携

 Silverlightでは、SilverlightをホストしているHTMLの要素を操作したり、HTML(JavaScript)からSilverlightの要素を操作することができます。つまりJavaScriptの代わりにPythonやRubyといった言語からSilverlightを通じてHTML DOMを操作することもできるということです。

 少し例を見てみましょう。リスト10はSilverlight Dynamic Languages SDKに含まれるslコマンドで生成したHTMLに、textBox1とbutton1というオブジェクトを追加した例です。

リスト10 IronPythonからHTMLを操作する例(HTML)
<html xmlns="http://www.w3.org/1999/xhtml" >
<head>
    <title>Silverlight Template</title>
      略
</head>
<body>
  <input type="text" id="textBox1" />
  <input type="button" id="button1" />

      略

    <object data="data:application/x-silverlight," type="application/x-silverlight-2" width="100%" height="100%">
      <param name="source" value="python.xap"/>

      略

</body>
</html>

 HTMLがロードされたときに、textBox1にメッセージを表示し、ボタンがクリックされたときにメッセージボックスを表示するコードをIronPythonを使って作成したいと思います。コードの例はリスト11のようになります。

リスト11 IronPythonからHTMLを操作する例(IronPython)
from System.Windows import Application
from System import EventHandler
from System.Windows.Browser import HtmlPage
from System.Windows.Browser.HtmlPage import Document

def Button1_Click(sender, event):
  HtmlPage.Window.Alert("ボタンクリック");

class App:
  def __init__(self):
    Document.textBox1.value = "Hello Python";

    handler = EventHandler(Button1_Click)
    Document.Button1.AttachEvent("onclick", handler)

App()

 Silverlightでは、System.Windows.Browser名前空間のクラスを使うことでHTML DOMにアクセスすることができます。IronPythonの初期化処理ではtextBox1にHello Pythonという文字列を表示し、ボタンがクリックされたときにメッセージボックスを表示するため、Button1_Clickというイベントハンドラが呼び出されるように設定します。

まとめ

 こうみると、インタラクティブな要素以外にも、現在の業務アプリケーションを作成する上で必須と言える機能が多く含まれる開発基盤としてSilverlightは大きな役割を持っていることが分かります。

 特に大きいのは、C#やVisual BasicといったCLRの言語を使用してアプリケーションを作成することでCLRによるコンパイル時の型解決の恩恵を享受しつつ、動的言語との連携で柔軟にアプリケーションの動作を変更できるということです。

 ぜひ一度Silverlightによるアプリケーションの開発を試してみてください。その開発生産性の高さに驚くかもしれませんよ。

  • LINEで送る
  • このエントリーをはてなブックマークに追加

著者プロフィール

  • 山田 祥寛(ヤマダ ヨシヒロ)

    静岡県榛原町生まれ。一橋大学経済学部卒業後、NECにてシステム企画業務に携わるが、2003年4月に念願かなってフリーライターに転身。Microsoft MVP for ASP/ASP.NET。執筆コミュニティ「WINGSプロジェクト」代表。 主な著書に「入門シリーズ(サーバサイドAjax/XM...

  • WINGSプロジェクト かるあ (杉山 洋一)(カルア(スギヤマ ヨウイチ))

    <WINGSプロジェクトについて> 有限会社 WINGSプロジェクトが運営する、テクニカル執筆コミュニティ(代表 山田祥寛)。主にWeb開発分野の書籍/記事執筆、翻訳、講演等を幅広く手がける。2018年11月時点での登録メンバは55名で、現在も執筆メンバを募集中。興味のある方は、どしどし応募頂...

All contents copyright © 2005-2021 Shoeisha Co., Ltd. All rights reserved. ver.1.5