独自メタデータタグを作る方法
Firefoxに初めて、並々ならぬ殺意を覚えた。
なに、俺が珍しくブログ書いてる時に何の前触れも無く落ちやがる。
もう、全部消えたやないけ!
泣くぞ?俺は泣くと手が付けられないんだからな!?
(ノ_<、)
恨み言はこれくらいにして、書き直します。
いいんだ、どうせ僕のポストなんて大宇宙の意思に比べたら全然小さいんだ。だから別に消えても世界は同じように回るんだ。
独自メタデータタグを作る方法
前回のポストでメタデータタグがあまりに便利だったので、オレオレメタデータタグが作りたくなった。以上。
投げやり?苦情はFirefoxに言ってくれ。
そんなこんなで、独自のメタデータタグを作る方法を調べてみました。
Annotating ActionScript Classes with Custom Metadata + Simple ORM Framework for AIR
http://coenraets.org/blog/2007/10/annotating-actionscript-classes-with-custom-metadata-simple-orm-framework-for-air/
AS3で独自メタデータの保持
http://www.be-interactive.org/?itemid=202
上のサイトは英語です。でも、独自メタデータをどうやって使うかがサンプルコードを見ると分かります。
describeTypeっていう関数を使って、インスタンスからクラス構造をXMLで取得できるので、そのXMLを解析すればメタデータタグの情報が取得できるってわけです。
下のサイトはBeInteractive!のyossyさんが独自メタデータタグを使ったコードのビルド方法について書かれている記事です。
これを参考にビルドしてみました。
サンプル
Player.as
{
public class Player
{
public function Player()
{
}
private var _test:String;
[DarkOmeme("programmer")]
public function set test(val:String):void
{
_test = val;
}
public function get test():String
{
return _test;
}
}
}
サンプルとしてこんなクラスを作ってみました。クラス名は適当です。本当は理由があったんだけど、迷宮入りです。Firefoxに言ってください。
testってプロパティにDarkOmemeって独自メタデータを付加して、値として"programmer"という文字列を渡しています。
さて、ではこいつのインスタンスを実際にdescribeTypeして見ましょう。
MetadataApp.mxml
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" creationComplete="onCreationComplete()">
<mx:Script>
<![CDATA[
import flash.utils.describeType;
import me.rkome.da.labs.Player;
private function onCreationComplete():void
{
var player:Player = new Player();
trace(describeType(player));
}
]]>
</mx:Script>
</mx:Application>
こんなアプリケーションを作ってみました。って事でビルドしてみましょう。
ビルドオプションはこんな感じ。
さて、結果はどう表示されるかというと。こんなん出ました。
<extendsClass type="Object"/>
<accessor name="test" access="readwrite" type="String" declaredBy="me.rkome.da.labs::Player">
<metadata name="DarkOmeme">
<arg key="" value="programmer"/>
</metadata>
</accessor>
</type>
オー、チャントDarkOmemeメタデータタグガフカサレテイルノガワカリマスネー。スゲーヤ。知ってるけどな!さっきやったから!
まー、あとはこのXMLを解析して煮るなり焼くなり、しましょうって事ですね。
次に、Flexでは有名なメタデータタグである[Bindable]を付加して同じようにdescribeTypeしてみました。そしたら、少し驚きだったんですよ。さっきね!
<extendsClass type="Object"/>
<implementsInterface type="flash.events::IEventDispatcher"/>
<method name="addEventListener" declaredBy="me.rkome.da.labs::Player" returnType="void">
<parameter index="1" type="String" optional="false"/>
<parameter index="2" type="Function" optional="false"/>
<parameter index="3" type="Boolean" optional="true"/>
<parameter index="4" type="int" optional="true"/>
<parameter index="5" type="Boolean" optional="true"/>
</method>
<method name="dispatchEvent" declaredBy="me.rkome.da.labs::Player" returnType="Boolean">
<parameter index="1" type="flash.events::Event" optional="false"/>
</method>
<method name="hasEventListener" declaredBy="me.rkome.da.labs::Player" returnType="Boolean">
<parameter index="1" type="String" optional="false"/>
</method>
<method name="removeEventListener" declaredBy="me.rkome.da.labs::Player" returnType="void">
<parameter index="1" type="String" optional="false"/>
<parameter index="2" type="Function" optional="false"/>
<parameter index="3" type="Boolean" optional="true"/>
</method>
<method name="willTrigger" declaredBy="me.rkome.da.labs::Player" returnType="Boolean">
<parameter index="1" type="String" optional="false"/>
</method>
<accessor name="test" access="readwrite" type="String" declaredBy="me.rkome.da.labs::Player">
<metadata name="Bindable">
<arg key="event" value="propertyChange"/>
</metadata>
<metadata name="DarkOmeme">
<arg key="" value="programmer"/>
</metadata>
</accessor>
</type>
なんと、IEventDispatcherが自動的に実装されてるじゃあ、ありませんか!自動的に!
どうやら、調べてみるとこれはmxmlc(Flexのコンパイラ)がメタデータタグを見つけてコードを自動生成するらしくて、これみたいなメタデータタグは今回の方法では作れないようです。
まあ、mxmlcはオープンソースなんで、オレオレmxmlcを作りましょうって事ですね。わかります。
今回はそこまで深入りしませんでした。
ただ、一応、mxmlcのソース(Javaで書かれている)を見に行ったんですが、どうやらコードを自動生成する部分はJavaでない、何やら良く分からないスクリプトで書かれていました。
多分、テンプレートエンジンみたいのを備えていて、そいつに通すと自動生成されるんだと思います。
さて、本当はmxmlcのメタデータタグみたいなのが作れるといいなあと思ったんですが、思ったよりヘビーなんでこの方法で何か出来ないか模索してみることにします。
最後に。
Firefoxさんいつもお世話になっています。ありがとう。
