DIコンテナを作ってみた
パフォーマンスがイマイチor要件に合わないコンテナが多かったので作ってみた
https://github.com/chalharu/BtInjector
nugetでBtInjectorで検索すると使えます
使い方
コンテナの登録
// まずコンテナインスタンスの作成
var container = new Container();
// シングルトンインスタンスの登録
// インターフェイス - 実体の型を登録
container.For<IService1>().As<Service1>(Lifecycle.Singleton);
// インスタンスを登録
container.For<IService2>().As(service2);
// ラムダ式で登録
container.For<IService3>().As(() => new Service3(), Lifecycle.Singleton);
container.For<IService4>().As((IService3 service3) => new Service4(service5), Lifecycle.Singleton);
// 都度生成の場合
// インターフェイス - 実体の型を登録
container.For<IService6>().As<Service6>(Lifecycle.Transient);
// ラムダ式で登録
container.For<IService7>().As(() => new Service7(), Lifecycle.Transient);
container.For<IService8>().As((IService7 service7) => new Service8(service7), Lifecycle.Transient);
// スレッド単位生成の場合
// インターフェイス - 実体の型を登録
container.For<IService9>().As<Service6>(Lifecycle.ThreadLocal);
// ラムダ式で登録
container.For<IService10>().As(() => new Service10(), Lifecycle.ThreadLocal);
container.For<IService11>().As((IService10 service10) => new Service11(service10), Lifecycle.ThreadLocal);
インスタンスの生成
// 通常通り生成
container.GetInstance<IService1>();
// 生成するデリゲートを出力
container.GetInstance<Func<IService6>>();
// 遅延生成
container.GetInstance<Lazy<IService7>>();
ポイント
- Funcで生成できる
- ラムダ式で登録できる
- かなり軽量(のつもり)
- いろんなプラットフォームに対応
- .NET Framwork 4.0
- PCL(Profile 5)
- iOS(実機がないので不明だがとりあえずFullAOTで動く)
- .NET Standard 1.1
DIコンテナを評価してみる
参考: http://www.nuits.jp/entry/ioc-battle-in-2017
前提条件
- MacBook Pro Retina 2014
- Memory 8G
- Mono 5.0.0
- .NET Framework 4.6.2ターゲット
評価内容
- Singlton時のコンテナ登録時間
- Singlton時の初回インスタンス取得時間
- Singlton時の2回目以降インスタンス取得時間(100万インスタンス)
- インスタンス都度生成時のコンテナ登録時間
- インスタンス都度生成時の初回インスタンス取得時間
- インスタンス都度生成時の2回目以降インスタンス取得時間(100万インスタンス)
変更点
- 初回インスタンス取得時間の追加
- 初回のインスタンス取得が非常に重たいコンテナが多く、別途測定する必要があると思われる
- Singletonと都度生成のそれぞれでAppDomainを生成した
- 型がキャッシュされている場合が多いため
評価結果
Container | Singleton - Registartion[ms] | Singleton - Resolve first[ms] | Singleton - Resolve[ms] | Transient - Registartion[ms] | Transient - Resolve first[ms] | Transient - Resolve[ms] |
---|---|---|---|---|---|---|
new Operator | 0.11 | 0.47 | 17.09 | 0.10 | 0.47 | 175.38 |
BtInjector | 3.18 | 26.20 | 79.25 | 3.19 | 25.15 | 299.24 |
BtInjector Lambda | 4.60 | 2.99 | 79.72 | 4.43 | 2.70 | 515.70 |
DryIoc.dll | 26.22 | 16.85 | 35.71 | 26.45 | 20.40 | 202.12 |
AutoFac | 38.48 | 56.94 | 758.52 | 39.45 | 63.03 | 35,440.41 |
AutoFac Lambda | 37.71 | 7.14 | 745.74 | 37.09 | 5.59 | 10,345.82 |
StructureMap | 30.50 | 105.62 | 1,026.37 | 27.60 | 98.85 | 7,869.01 |
SimpleInjector | 29.29 | 70.27 | 73.17 | 32.33 | 64.46 | 257.75 |
Unity | 24.60 | 90.24 | 1,041.28 | 23.61 | 86.98 | 24,289.29 |
BtInjectorはコンテナの登録・初回生成を含めるとかなり健闘しているはず。