2012-09-05 7 views
15

私は、NinjectがIoCコンテナとして使われるプロジェクトを持っています。私の関心は、クラスの多くは、コンストラクタのような種類があるということです。レイジー依存性注入

[Inject] 
public HomeController(
    UserManager userManager, RoleManager roleManager, BlahblahManager blahblahManager) { 
    _userManager = userManager; 
    _roleManager = roleManager; 
    _blahblahManager = blahblahManager; 
} 

私は一度にこれらのクラスのすべてのインスタンスを持ってしたくない場合は?

ところで、このすべてのクラスがLazy<T>でラップされ、コンストラクタに渡されたときの方法は、私が必要とするものではありません。 Tインスタンスはまだ作成されていませんが、Lazy<T>インスタンスはすでにメモリに保存されています。

私の同僚は、Factoryパターンを使用してすべてのインスタンス化を制御することを提案していますが、IoCにこのような優れた設計バグがあるかどうかはわかりません。

このような状況の回避策がありますか、またはIoCの設計に大きな欠点がありますか?多分私は別のIoCコンテナを使うべきでしょうか?

提案がありますか?

+0

実際にあなたの問題は何ですか?なぜあなたはこれらのインスタンスを望んでいないのですか? –

+2

コントローラの作業中にUserManagerが必要な場合がありますが、RoleManagerは必要なく、その逆もあります。 Lazy インスタンスについて話しているなら、これをメモリに入れるのは大したことではありませんが、これが唯一の方法ですか? – xwrs

+1

なぜ 'UserManager'と' RoleManager'にとって大したことですか?あなたのコンストラクタはとにかく重い作業をすべきではありません。 –

答えて

36

premature optimization:しないでください。

サービスのコンストラクタは、プライベートフィールドでの依存関係を格納するよりもnothing moreする必要があります。その場合、そのようなオブジェクトの作成は本当に軽量です。 .NETでのオブジェクト作成が本当に速いことを忘れないでください。ほとんどの場合、パフォーマンスの観点からは、依存関係が注入されるかどうかは関係ありません。特に、オブジェクトの量と比較すると、残りのアプリケーション(および使用するフレームワーク)が吐き出されています。実際のコストは、Webサービス、データベース、またはファイルシステム(または一般的なI/O)の使用を開始するときです。なぜなら、遅延がはるかに大きくなるからです。

作成は本当に高価である場合、これは一般的なアプリケーション・コードが作成を遅らせるためのメカニズムがあることに気づかずに滞在することを可能にするので、あなたは通常、Virtual Proxyの代わりに、すべての消費者でLazy<T>を注入後ろ作成を非表示にするには(アプリケーションコードとテストコードの両方が複雑になっています)。

Dependency Injection in .NET, second editionの第6章には、遅延プロキシと仮想プロキシについての詳細な説明が含まれています。

しかし、Lazy<T>だけ(32ビットプロセスを仮定し、その包まFunc<T>ための別の24 bytes)20のメモリのバイトを消費し、Lazy<T>インスタンスの作成は、実質的に自由です。したがって、あなたが本当に厳しいメモリ制約を伴う環境にいる場合を除いて、これについて心配する必要はありません。

メモリの消費量が問題になる場合は、一時的なものよりも長い寿命でサービスを登録してみてください。リクエストごと、ウェブリクエストごと、またはシングルトンごとに行うことができます。私は、新しいオブジェクトの作成が問題となる環境にいるときには、シングルトンサービスのみを使用するべきであると言います(ただし、Webアプリケーションを構築しているので、このような環境に取り組んでいる可能性は低いです) 。

Ninjectは.NET用のより遅いDIライブラリの1つです。それがあなたを悩ませているなら、switch to a faster container。一部のコンテナでは、オブジェクトグラフを手作業で新しくすることに近いパフォーマンスがあります。 しかし、是非これをプロファイルしてください。多くの開発者が間違った理由でDIライブラリを切り替えています。

依存関係としてLazy<T>を使用すると、leaky abstractionDependency Inversion Principleの違反)であることに注意してください。詳細については、this answerをお読みください。

+0

ありがとうございます。あなたは私の状況をより明確に理解しました。 – xwrs

+0

私はそれが時期尚早な最適化だとは思わない、この引数では、レイジーの必要性はないと思われますが、1つのオブジェクトを作成するのは重くなく、コンストラクタでいくつのオブジェクトを作成しているのか分かりません。そして、使用されないリモートリソースをいくつか開きます。 –

0

スティーブンが、これは時期尚早の最適化のように見えると言って正しいです。これらのオブジェクトの構築は非常に高速で、通常は決してボトルネックではありません。

ただし、依存関係を表現するためにLazyを使用すると、依存関係注入フレームワークで共通のパターンがすぐに必要なわけではありません。 Actofacは、various wrapping typesのサポートを組み込んだコンテナの1つです。私はNinjectの拡張もあると確信しています。おそらくこれを見てください。Ninject Lazy

+1

DIコンテナがLazy をサポートしているという事実は、アプリケーションコードがLazy の依存関係に依存するようにすることはできません。多くのDIコンテナは、ベストプラクティスを促進しない機能をサポートしています。 Dependency Injectionの観点から、Lazy は漏れた抽象である。 Lazy が漏洩する理由については、[this](https://stackoverflow.com/a/21724609/264697)を参照してください。 – Steven