« XMLHttpRequestを使わずにデータを受信する | トップページ | ASP.NETとAtlasでAjax »

2006年9月26日 (火)

.NETのリフレクション

.NET FrameworkのクラスライブラリにXmlSerializerというクラスがあります。
インスタンスのプロパティ値をXML形式でシリアライズしてくれるクラスで、簡単な使用例は以下のような感じです。

UserAccount.cs(この例ではAPS.NETで使用していますので、App_Code内に作成します)
using System;

public class UserAccount
{
    private string userName;

    public string UserName
    {
        get { return userName; }
        set { userName = value; }
    }

    private string mailAddress;

    public string MailAddress
    {
        get { return mailAddress; }
        set { mailAddress = value; }
    }
}

Serialize.aspx
<%@ Page Language="C#" %>

<script runat="server">
    void Page_Load()
    {
        UserAccount account = new UserAccount();
        account.UserName = "ユーザー名";
        account.MailAddress = "account@hoge.com";

        System.Xml.Serialization.XmlSerializer serializer =
            new System.Xml.Serialization.XmlSerializer(typeof(UserAccount));

        serializer.Serialize(Response.OutputStream, account);
        
        Response.End();
    }

</script>

このSerialize.aspxにアクセスすると、次のようなXMLが返ってきます。
<?xml version="1.0"?>
<UserAccount xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <UserName>ユーザー名</UserName>
  <MailAddress>account@hoge.com</MailAddress>
</UserAccount>
クラスのデータがXMLで出力されていますね。
便利なクラスです。

JSONでも出力したい、という要望が出たらどうしましょうか。
残念ながら、JSONでシリアライズするクラスはありませんので、JSONで出力するJsonSerializerというクラスを作ってみましょう。

データを保存するためには、まずオブジェクトが持つプロパティを列挙し、その値を取得出来なければなりません。
型情報からプロパティやメソッドの情報を取得したりするには、リフレクションを使います。

実際にやってみましょう。
JsonSerializer.cs
using System;
using System.IO;
using System.Reflection;

public class JsonSerializer
{
    private Type type;

    public JsonSerializer(Type type)
    {
        this.type = type;
    }

    public void Serialize(Stream stream, object instance)
    {
        string data = "";
        
        PropertyInfo[] properties = type.GetProperties();
        for (int i = 0; i < properties.Length; i++)
        {
            PropertyInfo property = properties[i];
            data += String.Format("'{0}' : '{1}'", 
                property.Name, property.GetValue(instance, null));
                
            if (i != properties.Length - 1)
                data += ",";
        }

        string json = type.Name + " = {" + data + "};";

        using (StreamWriter writer = new StreamWriter(stream))
        {
            writer.Write(json);
            writer.Close();
        }
    }
}
プロパティがさらにプロパティを持っていたりする場合が多いですので、実際に使用できるレベルにするにはもっと複雑になりますが、とりあえずはこんな感じです。

リフレクションの中心となるのはTypeというクラスで、型情報を持っています。
ObjectのGetType()メソッド、または typeof でインスタンスを取得します。

Typeクラスには、その型のメンバーを取得するGetPropertiesメソッドやGetMethodsメソッドなどがあり、今回はGetPropertiesメソッドでプロパティ を取得しています。
PropertyInfo[] properties = type.GetProperties();

このメソッドを呼び出すと、PropertyInfoというプロパティの情報を持つクラスの配列が戻ってきます。
PropertyInfoクラスは、プロパティの名前を取得したり、実際のインスタンスを渡して値を取得したりすることが出来ます。
PropertyInfo property = properties[i];
data += String.Format("'{0}' : '{1}'", property.Name, property.GetValue(instance, null));

それでは、このクラスを試してみましょう。
Serialize.aspxを以下のように書き換えます。
<%@ Page Language="C#" %>

<script runat="server">
    void Page_Load()
    {
        UserAccount account = new UserAccount();
        account.UserName = "ユーザー名";
        account.MailAddress = "account@hoge.com";

        JsonSerializer serializer = new JsonSerializer(typeof(UserAccount));

        serializer.Serialize(Response.OutputStream, account);
        
        Response.End();
    }

</script>

Serialize.aspxにアクセスすると、以下のようなデータが返ってきます。
(わかりやすいように改行を入れていますが、実際には改行はされません)
UserAccount = {
    'UserName' : 'ユーザー名',
    'MailAddress' : 'account@hoge.com'
};
JSON形式で出力されました。
なお、XMLとの対比という意味で、UserAccountというクラス名の部分も出力しています。

|

« XMLHttpRequestを使わずにデータを受信する | トップページ | ASP.NETとAtlasでAjax »

コメント

コメントを書く



(ウェブ上には掲載しません)




トラックバック

この記事のトラックバックURL:
http://app.cocolog-nifty.com/t/trackback/12438/12043016

この記事へのトラックバック一覧です: .NETのリフレクション:

« XMLHttpRequestを使わずにデータを受信する | トップページ | ASP.NETとAtlasでAjax »