.NET TIPS

[ASP.NET]DataBinder.Evalメソッドを使用するメリット/デメリットは?

デジタルアドバンテージ
2003/09/19

 ASP.NETにおいて、Repeater、DataList、DataGridなどのWebサーバ・コントロールでデータ連結を行う場合、データ連結式の記述でContainer.DataItemに対してDataBinder.Evalメソッドを使用する場合がある。しかし実のところ、データ連結式においてDataBinder.Evalメソッドは必ずしも必要というわけではない。このメソッドを使用するメリット/デメリットについてまとめてみる。

Container.DataItemについての復習

 「TIPS:[ASP.NET]Container.DataItemの正体は?」で解説しているように、データ連結式内ではContainer.DataItem」によりデータソース(コントロールのDataSourceプロパティで指定したコレクション)の各要素を参照することができる。

 例えば、aspxファイルで次のようなRepeaterコントロールを記述し、

  <asp:Repeater id="MyRepeater" runat="server">
    <ItemTemplate>
      <%# Container.DataItem %>
    </ItemTemplate>
  </asp:Repeater>

 このコントロールに対して、次のようなデータソースを設定した場合を考えてみる。

string[] cmajor = {"C", "C#", "D", "D#", "E"};
MyRepeater.DataSource = cmajor;

 MyRepeater.DataBindメソッドを呼び出してデータ連結を行った場合には、上記の<ItemTemplate>要素部分が5つの子コントロールに展開され、それぞれの<%# Container.DataItem %>の部分は文字列配列の各要素に置き換えられる。

 この場合には、反復されるデータソースの各要素そのものをデータ連結式で表示しているわけだが、各要素の特定のプロパティをRepeaterコントロールで表示したい場合について次に考えてみよう。

キャストが不要となるDataBinder.Evalメソッド

 ここでは、string型のプロパティ「Name」と、DateTime型のプロパティ「BirthDay」を持つクラス「Composer」が定義されているとしよう。そして次のようにして、このクラスのオブジェクトからなるコレクションを作成し、それをデータソースに設定したとする。

ArrayList comps = new ArrayList();
comps.Add(new Composer("Bach", "1685/3/21"));
comps.Add(new Composer("Mozart", "1756/1/27"));
comps.Add(new Composer("Beethoven", "1770/12/16"));
MyRepeater.DataSource = comps;

 今回Repeaterコントロールにより実際に表示したい項目は、各ComposerオブジェクトのNameプロパティとBirthDayプロパティである。このようなデータソースを設定した場合、データ連結式においてContainer.DataItemはデータソース内の各Composerオブジェクトを参照する。よって、各オブジェクトについてNameプロパティとBirthDayプロパティを表示するには、

<%# Container.DataItem.Name %>
<%# Container.DataItem.BirthDay %>

と記述したいところだが、これはコンパイル・エラーとなる。DataItemプロパティの型はobject型であり、objectクラスは当然ながらNameやBirthDayといったプロパティは持たないためだ(どのようなデータソースであっても参照できるように、DataItemプロパティはobject型である)。

 この場合Container.DataItemをComposer型にキャストする必要があり、正しいデータ連結式の記述は次のようになる。

<%# ((Composer)Container.DataItem).Name %>
<%# ((Composer)Container.DataItem).BirthDay %>

 さて、ここでDataBinder.Evalメソッドの出番となる。このメソッドを使用すると、上の2行は次のように「キャストなし」で記述することができる。

<%# DataBinder.Eval(Container.DataItem, "Name") %>
<%# DataBinder.Eval(Container.DataItem, "BirthDay") %>

 これがDataBinder.Evalメソッドを使用する第1のメリットである。

 Composerクラスを使用した実際のサンプル・プログラムとその実行結果は次のようになる。

サンプル・プログラムの実行結果

DataBinder.Evalメソッドの動作

 DataBinderクラス(System.Web.UI名前空間)のstaticなメソッドであるEvalメソッドはデータ連結式内で使用される場合がほとんどであるが、データ連結式に依存した特別な機能を持っているわけではない。次のような簡単なC#のサンプル・プログラムを例にしてDataBinder.Evalメソッドの動作について見てみよう。

// binder.cs

using System;
using System.Web.UI;

public class BinderEvalTest {
  static void Main() {

    string[] colors = {"red", "green", "blue"};

    int len1 = colors.Length;
    int len2 = (int)DataBinder.Eval(colors, "Length");

    Console.WriteLine("{0}, {1}", len1, len2);
    // 出力:3, 3

    int len3 = colors[1].Length;
    int len4 = (int)DataBinder.Eval(colors, "[1].Length");
    int len5 = (int)DataBinder.Eval(colors[1], "Length");

    Console.WriteLine("{0}, {1}, {2}", len3, len4, len5);
    // 出力:5, 5, 5

    string str1 = colors.ToString();
    // string str2
    //   = (string)DataBinder.Eval(colors, "ToString()");
    // 実行時にエラーとなる。

  }
}

// コンパイル方法:csc binder.cs
DataBinder.Evalメソッドをテストするサンプル・プログラム(binder.cs)

 最初の例はDataBinder.Evalメソッドによりプロパティの値を取得している。

int len1 = colors.Length;
int len2 = (int)DataBinder.Eval(colors, "Length");

 DataBinder.Evalメソッドは、第1パラメータで指定したオブジェクトに対して、第2パラメータで指定した名前を持つプロパティの値を取得することができる。

 このような処理が可能な理由は、.NET Frameworkが「リフレクション」と呼ばれる機能を持っているためだ。リフレクション機能を使用すると、実行時に、オブジェクトが定義しているプロパティ名やメソッド名を列挙したり、文字列で指定したプロパティの値の取得や、文字列で指定したメソッドを呼び出したりできる。

 DataBinder.Evalメソッドは、次のような大括弧を伴うインデクサによる値の取得時にも使用可能だ。

int len3 = colors[1].Length;
int len4 = (int)DataBinder.Eval(colors, "[1].Length");
int len5 = (int)DataBinder.Eval(colors[1], "Length");

 このように、DataBinder.Evalメソッドの処理はメソッドの2つのパラメータを連結したものを実行するようなイメージだが、メソッドの呼び出しはできない。

string str1 = colors.ToString();
string str2 = (string)DataBinder.Eval(colors, "ToString()");

 変数str2に代入を行っている2行目の記述は、実行時にエラーとなる。

DataBinder.Evalメソッドによる文字列の整形

 DataBinder.Evalメソッドには、キャストが不要となることに加えて、もう1つの有用な機能がある。文字列の整形である。

 Composerクラスを用いた最初のサンプル・プログラム(composer.aspx)ではDateTime型のプロパティBirthDayをそのまま表示していたが、これを“YYYY-MM-DD”の形式で表示したいとしよう。DataBinder.Evalメソッドを使わずに行う1つの方法は、次のようなメソッドを用意することだ。

public string GetYYYYMMDD(object o) {
  Composer c = (Composer)o;
  return String.Format("{0:yyyy-MM-dd}", c.BirthDay);
}

 Stringクラス(System名前空間)のFormatメソッドは、指定した書式でオブジェクトを文字列化するためのstaticなメソッドだ。このようなメソッドを用意したとすると、データ連結式の記述でこのメソッドを直接呼び出すことができる。

<%# GetYYYYMMDD(Container.DataItem) %>

 オーバーロードされた別バージョンのDataBinder.Evalメソッドを使えば、文字列を整形するためのメソッドを用意せずに次のようにして同等な記述が可能である。

<%# DataBinder.Eval(Container.DataItem, "BirthDay", "{0:yyyy-MM-dd}") %>

 このDataBinder.Evalメソッドは、反復される要素の特定のプロパティを書式付きでテキスト化することができる。第3パラメータには書式を表す文字列を指定する。このDataBinder.Evalメソッドは内部でString.Formatメソッドを呼び出しているようで、このパラメータにはString.Formatメソッドの第1パラメータと同様な書式文字列が指定可能だ。

DataBinder.Evalメソッドの欠点

 データ連結式では、反復されるデータソースの項目に対して、そのプロパティを書式付きで表示することが多い。DataBinder.Evalメソッドは、そういった処理の記述を容易にするために用意されたメソッドであるといえる。

 しかし、DataBinder.Evalメソッドはリフレクション機能を使用しているため、実行に時間がかかるという欠点がある。

 上記のサンプル・プログラム(binder.cs)を少し改造して、len1からlen5までの呼び出しを100万回実行するのにかかった時間を筆者のPCで計測したところ、len1、len3が計測不可能なぐらい一瞬で終わるのに対して、

「int len2 = (int)DataBinder.Eval(colors, "Length");」は約4秒、
「int len4 = (int)DataBinder.Eval(colors, "[1].Length");」は約7秒、
「int len5 = (int)DataBinder.Eval(colors[1], "Length");」は約3秒、

の時間がかかった。ページ内にデータ連結を行う項目が多いような場合には注意が必要だ。サーバに負荷がかかる場合には、記述は多少煩雑になるがDataBinder.Evalメソッドの使用をやめることができる。End of Article

カテゴリ:Webフォーム 処理対象:コントロール
使用ライブラリ:Repeaterコントロール
使用ライブラリ:DataBinderクラス(System.Web.UI名前空間)
使用ライブラリ:Stringクラス(System名前空間)
関連TIPS:[ASP.NET]Container.DataItemの正体は?
 
この記事と関連性の高い別の.NET TIPS
[ASP.NET]Container.DataItemの正体は?
[ASP.NET]DataGridコントロールのハイパーリンク列で複数のパラメータをデータ連結するには?
[ASP.NET]DataGridコントロールの行に通し番号を付けるには?
[ASP.NET]DataGridコントロールでテンプレート列のセルの値を取得するには?
[ASP.NET]DataGridコントロールでページ表示するには?
このリストは、(株)デジタルアドバンテージが開発した
自動関連記事探索システム Jigsaw(ジグソー) により自動抽出したものです。
generated by

「.NET TIPS」

TechTargetジャパン

Insider.NET フォーラム 新着記事
@ITメールマガジン 新着情報やスタッフのコラムがメールで届きます(無料)

キャリアアップ


- PR -

イベントカレンダー

PickUpイベント

- PR -

アクセスランキング

もっと見る
- PR -

ホワイトペーパーTechTargetジャパン

ソリューションFLASH

「ITmedia マーケティング」新着記事

博報堂生活総研、2014年のヒット商品分析レポートを発表
博報堂生活総合研究所は11月26日、2014年に生活者が関心を示したモノやサービス、コンテ...

アドビ、APAC地域におけるデジタルマーケティング活動の調査結果を発表
アドビ システムズ(以下、アドビ)は11月25日、アジア太平洋地域各国100名以上のマーケ...

第6回 チーフデータオフィサー(CDO)の必要性
前回は「データ活用を成功させるためポイント」として、1)ビッグデータへの対応、2)IT...