無料で使えるシステムトレードフレームワーク「Jiji」 をリリースしました!

・OANDA Trade APIを利用した、オープンソースのシステムトレードフレームワークです。
・自分だけの取引アルゴリズムで、誰でも、いますぐ、かんたんに、自動取引を開始できます。

JavaScriptで動くDIコンテナに機能を追加しました。

以前作成したJavaScriptで動くDIコンテナにこっそり機能を追加していたので公開してみます。
新機能は次の3つです。

  1. コンポーネント定義を列挙するAPIの追加。
  2. 関数実行結果のインジェクションをサポート。
  3. EagerSingletonスコープ

コンポーネント定義の列挙

Container#eachComponentDef()、Container#eachComponentDefs()で登録済みのコンポーネント定義を列挙します。DIコンテナの基本機能ですね。どちらも引数でコールバック関数を指定します。

var stdout = document.getElementById( "stdout" );

// クラス
function Kitten() {}
Kitten.prototype = {
   getName: function () { return this.name; }
};

// コンテナを作成。
var c = new container.Container( function( binder ) {
  binder.bind( "kitten" ).to( Kitten ).inject( { "name": "mii" } );
  binder.bind( "kitten" ).to( Kitten ).inject( { "name": "shiro" } );
  binder.bind( "kitten" ).to( Kitten ).inject( { "name": "kuro" } );

  binder.bind( "tiger"  ).to( Kitten ).inject( { "name": "tora" } );
});

// コンポーネント定義を列挙
c.eachComponentDef( function( name, def ) {
  // 第1引数はコンポーネント名
  // 第2引数はコンポーネント定義
  stdout.innerHTML += name + ":" + def[container.Annotation.Container][container.Annotation.Inject]["name"] + "<br/>";
});

stdout.innerHTML += "<br/>";

// コンポーネント定義を名前ごとに列挙
c.eachComponentDefs( function( name, defs ) {
  // 第1引数はコンポーネント名
  // 第2引数はコンポーネント定義の配列
  stdout.innerHTML += name + ":" + defs.length + "<br/>";
});

実行結果です

コンポーネント定義

引数として渡されるコンポーネント定義のデータ構造は次の通りです。

var def = {
  // コンポーネントの設定 / アノテーションと同様のデータ構造を持つ。
  "@Container": {
    "@Inject": { ... },
    "@Scope" : container.Scope.Singleton,
    ...
  },
  // コンポーネントを生成する関数。
  constractor: function() {...}
  
  // 作成されたコンポーネント(prototype以外で、既に作成済みであれば。)
  instance: ....
}

関数実行結果のインジェクション

決められた手順で関数をインジェクションすることで、関数の実行結果をインジェクションできるようにしました。インジェクションする値を実行時に決定したい場合に使用します。

var c = new container.Container( function( binder ) {
  binder.bind( "kitten" ).to( Kitten ).inject( {
      // 関数の戻り値をインジェクションする
      "name": container.provides( function () {
            return location.hash || "mii"; // URLのロケーションを名前にする。
      })
  });
});
var kitten = c.get("kitten");
stdout.innerHTML += kitten.getName();

実行結果です("#shiro"を表示)
実行結果です("#tora"を表示)

EagerSingletonスコープ

コンポーネントのスコープに「EagerSingleton」を追加しました。「EagerSingleton」スコープとされたコンポーネントはコンテナの作成時に生成されます。(Singletonの場合、コンテナから初めてコンポーネントを取得した際に生成される。)これを利用して、コンテナに登録しておくだけで効果を発揮するコンポーネントを作成できるようになります。

// コンテナを作成。
var c = new container.Container( function( binder ) {
  binder.bind( "kitten" ).to( Kitten ).inject( { "name": "mii" } )
      .scope( container.Scope.EagerSingleton ) // EagerSingletonとする
      .initialize( function( obj, container ) {
          // コンテナ生成時にコンポーネントも作成される。
          // コンポーネントを取得しなくても以下の処理が実行される。
          stdout.innerHTML += obj.getName() + "<br/>";
      } );
});

実行結果です

ダウンロード

ダウンロードはこちらから。
container.js(コンテナ本体) ver0.2.0
テストケースの実行結果

  • ※動作確認はIE6とFireFoxで行っています。
  • ※仕様を追加したのでマイナーバージョンを上げて0.2.0としました。

あとがき

趣味アプリで使おうと画策中だけど、ネタがないのです。それなりに大きいプログラムじゃないと使う意味ない気がするし。むー。
あと、そろそろ名前付けたい。「JavaScriptで動くDIコンテナ」とか書くの面倒になってきた。