我最近发现了 [FromServices] 属性,它自 .Net Core 第一个版本以来就已经存在。
[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 工程师,拥有近 30 年的软件工程经验。他构建实用的 AI 系统——内容管道、基础设施代理和解决实际问题的工具——并分享他沿途的学习成果。在社交媒体上与他联系:X (@chuckconway) 或访问他的 YouTube 和 SubStack。