
最近、.Net Coreの最初のバージョンから存在している[FromServices]
属性を発見しました。
[FromServices]属性は、Asp.Net Coreコントローラーでメソッドレベルの依存性注入を可能にします。
以下に例を示します:
public class UserController : Controller
{
private readonly IApplicationSettings _applicationSettings;
public UserController(IApplicationSettings applicationSettings)
{
_applicationSettings = applicationSettings;
}
public IActionResult Get([FromService]IUserRepository userRepository, int userId)
{
//Do magic
}
}
なぜコンストラクター注入よりもメソッド注入を使うのでしょうか?一般的な説明は、メソッドが依存関係を必要とし、それが他の場所で使用されない場合、[FromService]
属性を使用する候補になるということです。
StackOverflowのStevenが[FromService]
属性の使用に反対する回答を投稿しました:
私にとって、コントローラーアクションへのこの種のメソッド注入の使用は悪いアイデアです。なぜなら:
– そのような
[FromServices]
属性は簡単に忘れられる可能性があり、アクションが呼び出されたときにのみ発見することになります(アプリケーションの設定を検証できるアプリケーション起動時に発見する代わりに)– パフォーマンス上の理由でコンストラクター注入から離れる必要があるということは、注入されたコンポーネントの作成が重すぎることを明確に示しており、注入コンストラクターはシンプルであるべきで、したがってコンポーネントの作成は非常に軽量であるべきです。
– コンストラクターが大きくなりすぎることを防ぐためにコンストラクター注入から離れる必要があるということは、クラスが多くの依存関係を持ちすぎて複雑になりすぎていることを示しています。言い換えれば、多くの依存関係を持つことは、クラスが単一責任原則に違反していることを示しています。コントローラーアクションが異なるクラスに簡単に分割できるという事実は、そのようなコントローラーがあまり結合していないことの証拠であり、したがってSRP違反の兆候です。
そのため、メソッド注入の使用で根本的な問題を隠すのではなく、ここでは唯一の注入パターンとしてコンストラクター注入を使用し、コントローラーを小さくすることをお勧めします。ただし、これはルーティングスキームがクラス構造と異なることを意味する可能性がありますが、これは完全に問題なく、ASP.NET Coreで完全にサポートされています。
ちなみに、テスト可能性の観点から、時々必要のない依存関係があっても実際には問題ありません。この問題を解決する効果的なテストパターンがあります。
私はStevenに同意します。クラスが多くの依存関係を構築しているためにコントローラーから依存関係をメソッドに移動する必要がある場合、コントローラーを分割する時期です。ほぼ確実にSRPに違反しています。
メソッド注入で私が見る唯一の使用例は、コントローラー構築時に準備ができていない依存関係の遅延バインディングです。それ以外の場合は、コンストラクター注入を使用する方が良いでしょう。
これは、コンストラクター注入では、クラスが構築時に依存関係が利用可能かどうかを知っているからです。メソッド注入では、これは当てはまらず、メソッドが呼び出されるまで依存関係が利用可能かどうかがわかりません。
著者:Chuck Conwayはソフトウェアエンジニアリングと生成AIを専門としています。ソーシャルメディアで彼とつながりましょう:X (@chuckconway) または YouTube をご覧ください。