はい、オブジェクトのインスタンス化をスタックの上に移動しています。しかし、実際にどの実装を使用するかをより適切に決定できる場所にスタックを移動しています。ビジネス ロジックのパフォーマンス テストを行うために、データ アクセス レイヤーをスタブ バージョンに置き換えたい場合、ビジネス ロジック コードを 1 行も変更する必要はありません。
依存関係を注入する方法はたくさんあります。私の場合、どこでもコンストラクター注入を使用します。このメソッドを使用すると、下位レベルのクラスが依存関係を必要とする場合、その依存関係のインターフェイスをコンストラクターに配置するだけです。スタックの上位クラスから渡す必要はありません。両方のクラスで同じインスタンスが必要な場合は、依存関係をコンテナに登録するときのライフスタイル/スコープを調べて、両方のクラスに同じインスタンスが渡されるようにする必要があります。
一部の DI 実装では、遅延読み込みを使用してオブジェクトをインスタンス化します。(つまり、実際にインスタンス化されるのは、オブジェクトを使用しようとするまでではありません)。そうでないものもあります。また、パフォーマンスを低下させるには、かなり大きな依存関係グラフが必要になります。コンストラクターをシンプルかつ高速に保つ (とにかく良い習慣です) と、これは問題にはなりません。また、DI コンテナーは、使用されなくなったオブジェクトを解放するのが賢明です (ここでも、ライフスタイル/スコープに特に注意してください)。
これが役立つことを願っています。