CSSを設定ファイルに使用した、Flex2用のDIコンテナを作成しました。
ライブラリとソース
http://code.google.com/p/asphalt2/のFeatured Downloadsから、asphalt2container_v0_01_00.zipをダウンロードしてください。
これ自体がeclipseプロジェクトになっています。またbinフォルダにswcファイルが、srcフォルダにソースが入っています。
ライブラリだけ使う場合は、asphalt2container.swcをプロジェクトにいれパスを通すと、使用可能になります。
SVNでチェックアウトしたい場合は、
http://asphalt2.googlecode.com/svn/trunk/asphalt2container-project/asphalt2container/
をチェックアウトしてください。
また
http://asphalt2.googlecode.com/svn/trunk/asphalt2container-project/asphalt2container-test/
がテストプロジェクトになっていますので、こちらももっていくといいと思います。
ClassReference
Flex2のCSSには「ClassReference」という組み込み関数があります。
例えば
Panel{ border-skin:ClassReference("panelskin.Border"); }
としておくと、panelskin.Borderというクラスを使用して、Panelの枠を描画できます。
この関数をCSS内で使用すると、
・型の存在チェックをしてくれる
・宣言した型は、swf内に読みこんでくれる
という機能を使うことが出来ます。
元々画面のスタイルを定義するための機能ですが、この2つの特徴はDIコンテナを作成するのにはとても便利なため、CSSを定義ファイルに用いることにしました。
BeanFactory
インスタンスを取り出すためのインターフェースとして、「BeanFactory」というインターフェースを定義しています。
Spring先生ありがとうございます。
/** * Bean生成Factoryインターフェース * @auther c9katayama */ public interface BeanFactory { /** * beanNameを使用してbeanを検索し、beanインスタンスを返します。 */ function getBean(beanName:String):Object; /** * Classを使用してbeanを検索し、beanインスタンスを返します。 */ function getBeanByType(clazz:Class):Object; }
また、この実装クラスとして、「CSSBeanFactory」というクラスを実装してあります。
実際に使用するのは、このクラスです。
使用方法
はじめに、インターフェースを実装クラスを作成します。
//インターフェース定義 public interface Hoge{ function printName():void; } //実装定義 public class HogeImpl implements Hoge{ private var name:String; public function set name(value:String):void{ _name = value; } public function printName():void{ trace(_name); } }
次に、CSSを使用して設定ファイルを記述します。(例えばbeans.cssというような名前で保存します)
Hoge{ bean-type:ClassReference("bean.impl.HogeImpl"); bean-scope:singleton; name:"HOGE"; } .hogehoge{ bean-type:ClassReference("bean.impl.HogeImpl"); bean-scope:prototype; name:"HOGE_HOGE"; }
設定ファイルを、アプリケーションに読み込ませます。
最後に、BeanFactoryからBeanを取得します。
var factory:BeanFactory = CSSBeanFactory.getInstance(); var hoge:Hoge = factory.getBeanByType(Hoge) as Hoge; hoge.printName();// "HOGE" と出力される var hogehoge:Hoge = factory.getBean("hogehoge") as Hoge; hogehoge.printName();// "HOGE_HOGE" と出力される
読み込ませるCSSを変える事で、取得するインスタンスを変えることが出来ます。
またCSSをコンパイルしてswfにしておけば、動的にロードすることも(多分)できます。
設定ファイル
CSSのタイプセレクタ(上記だとHoge{}のセレクタ)は、主にBeanFactory#getBeanByType()を使用するときに使います。
BeanFactory#getBean("Hoge")でもgetBeanByType(Hoge)と同様に値を取得できますが、ByTypeの方が型チェックが入るのでいいとおもいます。
クラスセレクタは、BeanFactory#getBean()でbeanを取得する際に使用します。
セレクタで宣言が必須なのが、「bean-type」のプロパティです。
このプロパティでは、実際にインスタンス化する型を定義します。
スコープ宣言を行うのが、「bean-scope」のプロパティです。
「singleton」と「prototype」が宣言できます。
宣言のない場合、singletonスコープが適用されます。
それ以外は、インスタンスに設定するプロパティとみなします。文字列、数値、配列がサポートされています。
また、「${}」の記述を使用すると、ほかのbeanをインジェクトすることができます。
例えば
HogeService{ bean-type:ClassReference("test.asphalt2.factory.impl.HogeServiceImpl"); barService:"${BarService}"; } BarService{ bean-type:ClassReference("test.asphalt2.factory.impl.BarServiceImpl"); bar:100; }
とすると、HogeServiceのbarServiceプロパティに、BarServiceで取得できるbeanがインジェクトされます。
今後
${}を導入したので、ognl式をある程度評価できるようになったら便利かなと思ったり、${fn:today()}とかあっても便利かなと思いました。
あとはプロパティインジェクト時の型変換でしょうか。String->Dateぐらいは変換できるようにしたいと思います。
あと、Embed関数でがんばればいいと思っているので、いまのところ非同期的なプロパティ取得(たとえばcsvファイルのロードとか)は考えていません。