20

NinjectをIoCコンテナとして使用するプロジェクトがあります。私の懸念は、多くのクラスがそのような種類のコンストラクターを持っていることです。

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

これらのクラスのすべてのインスタンスを一度に取得したくない場合はどうなりますか?

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

同僚は、ファクトリパターンを使用してすべてのインスタンス化を制御することを提案していますが、IoCにこのような大きな設計上のバグがあるかどうかはわかりません。

この状況の回避策はありますか、それともIoCの設計に本当に大きな欠陥がありますか?たぶん私は別のIoCコンテナを使うべきですか?

助言がありますか?

4

3 に答える 3

50

あなたは時期尚早の最適化をしているように私には思えます:それをしないでください。

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

作成に非常に費用がかかる場合は、通常、すべてのコンシューマーにを挿入するのではなく、仮想プロキシの背後に作成を非表示にする必要があります。Lazy<T>これにより、一般的なアプリケーションコードは、作成を遅らせるメカニズムがあるという事実に気づかないままになります(両方のアプリケーションこれを行うと、コードとテストコードがより複雑になります)。

依存性注入の第8章:原則、実践、パターンには、レイジープロキシと仮想プロキシに関するより詳細な説明が含まれています。

ただし、aは20バイトのメモリ(および32ビットプロセスを想定した場合、ラップされたものにはさらに24バイトLazy<T>)を消費するだけであり、インスタンスの作成は実質的に無料です。したがって、メモリの制約が非常に厳しい環境にいる場合を除いて、これについて心配する必要はありません。Func<T>Lazy<T>

また、メモリ消費が問題になる場合は、一時的なものよりも長いライフタイムでサービスを登録してみてください。リクエストごと、Webリクエストごと、またはシングルトンで実行できます。新しいオブジェクトの作成が問題となる環境にいるときは、おそらくシングルトンサービスのみを使用する必要があります(ただし、Webアプリを構築しているため、そのような環境で作業している可能性は低いです)。 。

Ninjectは、.NET用の低速なDIライブラリの1つであることに注意してください。それがあなたを悩ませているなら、より速いコンテナに切り替えてください。一部のコンテナは、オブジェクトグラフを手動で更新するのに近いパフォーマンスを備えています。しかし、どうしても、これをプロファイリングしてください。多くの開発者は、間違った理由でDIライブラリを切り替えます。

Lazy<T>依存関係としての使用は、漏れのある抽象化(依存性逆転の原則の違反)であることに注意してください。詳細については、この回答をお読みください。

于 2012-09-05T16:01:43.100 に答える
2

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

ただし、Lazyを使用して依存性を表現することは、依存性注入フレームワークの一般的なパターンです。Actofacは、さまざまなラッピングタイプのサポートが組み込まれているそのようなコンテナの1つです。Ninjectの拡張機能もあると思います。おそらく、これ、NinjectLazyを見てください。

于 2014-09-11T22:58:37.153 に答える
1

以下の構文を使用して、アクションメソッドに注入することもできます。(これが導入されたバージョンは正確にはわかりません)。

コンストラクターがベストプラクティスですが、高価な初期化を行っていたサービスがあったときに、これを意図的に行う必要がありました-実際には偶然です-しかし、しばらくの間発見されなかったため、1つのメソッドに移動するのが最も簡単でしたそれそれを必要としていました。

これにより、1つのアクションメソッドからサービスにアクセスするだけでよい場合に、よりクリーンなコードを作成できます。ただし、メソッドに挿入する場合は、オンではなくなるため、どこにでも渡す必要があることに注意してthisください。アクションメソッドで割り当てを行わないでくださいthis.service-それは恐ろしいことです。

public IActionResult About([FromServices] IDateTime dateTime)
{
    ViewData["Message"] = "Currently on the server the time is " + dateTime.Now;

    return View();
}

https://docs.microsoft.com/en-us/aspnet/core/mvc/controllers/dependency-injection?view=aspnetcore-2.2#action-injection-with-fromservices

于 2019-01-27T08:20:01.267 に答える