起因

这两天,我忽然有点怀念 Asp.NET MVC 5 之前的时代,原因是我看到项目里面有这么一段代码(其实不止一段,几乎每个 Controller 都是)

    [Route("home")]
[ApiController]
public class HomeController : ControllerBase
{
private readonly IConfiguration configuration;
private readonly IHostingEnvironment environment;
private readonly CarService carService;
private readonly PostServices postServices;
private readonly TokenService tokenService;
private readonly TopicService topicService;
private readonly UserService userService; public HomeController(IConfiguration configuration,
IHostingEnvironment environment,
CarService carService,
PostServices postServices,
TokenService tokenService,
TopicService topicService,
UserService userService)
{
this.configuration = configuration;
this.environment = environment;
this.carService = carService;
this.postServices = postServices;
this.tokenService = tokenService;
this.topicService = topicService;
this.userService = userService;
} [HttpGet("index")]
public ActionResult<string> Index()
{
return "Hello world!";
}
}

在构造函数里面声明了一堆依赖注入的实例,外面还得声明相应的接收字段,使用代码克隆扫描,零零散散的充斥在各个 Controller 的构造函数中。在 Asp.NET MVC 5 之前,我们可以把上面的代码简化为下面的形式:

    [Route("home")]
[ApiController]
public class HomeController : ControllerBase
{
[FromServices] public IConfiguration Configuration { get; set; }
[FromServices] public IHostingEnvironment Environment { get; set; }
[FromServices] public CarService CarService { get; set; }
[FromServices] public PostServices PostServices { get; set; }
[FromServices] public TokenService TokenService { get; set; }
[FromServices] public TopicService TopicService { get; set; }
[FromServices] public UserService UserService { get; set; } public HomeController()
{
} [HttpGet("index")]
public ActionResult<string> Index()
{
return "Hello world!";
}
}

但是,在 .NETCore 中,上面的这断代码是会报错的,原因就是特性:FromServicesAttribute 只能应用于 AttributeTargets.Parameter,导航到 FromServicesAttribute 查看源码

namespace Microsoft.AspNetCore.Mvc
{
/// <summary>
/// Specifies that an action parameter should be bound using the request services.
/// </summary>
/// <example>
/// In this example an implementation of IProductModelRequestService is registered as a service.
/// Then in the GetProduct action, the parameter is bound to an instance of IProductModelRequestService
/// which is resolved from the request services.
///
/// <code>
/// [HttpGet]
/// public ProductModel GetProduct([FromServices] IProductModelRequestService productModelRequest)
/// {
/// return productModelRequest.Value;
/// }
/// </code>
/// </example>
[AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false, Inherited = true)]
public class FromServicesAttribute : Attribute, IBindingSourceMetadata
{
/// <inheritdoc />
public BindingSource BindingSource => BindingSource.Services;
}
}

那么问题来了,AttributeUsage 是什么时候移除了 AttributeTargets.Property 呢?答案是:2015年11月17日,是一个叫做 Pranav K 的哥们革了 FromServiceAttribute 的命,下面是他的代码提交记录

Limit [FromServices] to apply only to parameters

https://github.com/aspnet/Mvc/commit/2a89caed05a1bc9f06d32e15d984cd21598ab6fb

这哥们的 Commit Message 很简洁:限制 FromServices 仅作用于 parameters 。高手过招,人狠话不多,刀刀致命!从此,广大 .NETCore 开发者告别了属性注入。经过我不懈努力的搜索后,发现其实在 Pranav K 提交代码两天后,他居然自己开了一个 Issue,你说气人不?

关于废除 FromServices 的讨论

https://github.com/aspnet/Mvc/issues/3578

在这个贴子里面,许多开发者表达了自己的不满,我还看到了有人像我一样,表达了自己想要一个简洁的构造函数的这样朴素的请求;但是,对于属性注入可能导致滥用的问题也产生了激烈的讨论,还有属性注入要求成员必须标记为 public 这些硬性要求,不得不说,这个帖子成功的引起了人们的注意,但是很明显,作者不打算修改 FromServices 支持属性注入。

自己动手,丰衣足食

没关系,官方没有自带的话,我们自己动手做一个也是一样的效果,在此之前,我们还应该关注另外一种从 service 中获取实例的方式,就是常见的通过 HttpContext 请求上下文获取服务实例的方式:

 var obj = HttpContext.RequestServices.GetService(typeof(Type));

上面的这种方式,其实是反模式的,官方也建议尽量避免使用,说完了废话,就自动动手撸一个属性注入特性类:PropertyFromServiceAttribute

[AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = true)]
public class PropertyFromServiceAttribute : Attribute, IBindingSourceMetadata
{
public BindingSource BindingSource => BindingSource.Services;
}

没有多余的代码,就是标记为 AttributeTargets.Property 即可

应用到类成员
    [Route("home")]
[ApiController]
public class HomeController : ControllerBase
{
[PropertyFromService] public IConfiguration Configuration { get; set; }
[PropertyFromService] public IHostingEnvironment Environment { get; set; }
[PropertyFromService] public CarService CarService { get; set; }
[PropertyFromService] public PostServices PostServices { get; set; }
[PropertyFromService] public TokenService TokenService { get; set; }
[PropertyFromService] public TopicService TopicService { get; set; }
[PropertyFromService] public UserService UserService { get; set; } public HomeController()
{ } [HttpGet("index")]
public ActionResult<string> Index()
{
return "Hello world!";
}
}

请大声的回答,上面的代码是不是非常的干净整洁!但是,像上面这样使用属性注入有一个小问题,在对象未初始化之前,该属性为 null,意味着在类的构造函数中,该成员变量不可用,不过不要紧,这点小问题完全可用通过在构造函数中注入解决;更重要的是,并非每个实例都需要在构造函数中使用,是吧。

示例代码

托管在 Github 上了 https://github.com/lianggx/Examples/tree/master/Ron.DI

** 如果你喜欢这篇文章,请给我点赞,让更多同学可以看到,笔芯~

Asp.NETCore让FromServices回来的更多相关文章

  1. FromServices回来

    FromServices回来 起因 这两天,我忽然有点怀念 Asp.NET MVC 5 之前的时代,原因是我看到项目里面有这么一段代码(其实不止一段,几乎每个 Controller 都是) [Rout ...

  2. Asp.NetCore之组件写法

    本章内容和大家分享的是Asp.NetCore组件写法,在netcore中很多东西都以提供组件的方式来使用,比如MVC架构,Session,Cache,数据库引用等: 这里我也通过调用验证码接口来自定义 ...

  3. Server in ASP.NET-Core

    .NET-Core Series Server in ASP.NET-Core DI in ASP.NET-Core Routing in ASP.NET-Core Error Handling in ...

  4. 为ASP.NetCore程序启用SSL

    紧接着上一篇搭建连接MySql的三层架构的ASP.NetCore2.0的WebApi的案例,这篇来实现为ASP.NetCore启用SSL支持 由于ASP.NetCore默认服务器Kestrel不像ii ...

  5. AutoMapper在asp.netcore中的使用

    # AutoMapper在asp.netcore中的使用  automapper 是.net 项目中针对模型之间转换映射的一个很好用的工具,不仅提高了开发的效率还使代码更加简洁,当然也是开源的,htt ...

  6. ASP.NETCore的Kestrel服务器

    什么是Kestrel服务器 Kestrel是开源的(GitHub提供的源代码),事件驱动的异步I / O服务器,用于在任何平台上托管ASP.NET应用程序.这是一个监听服务器和一个命令行界面.您将侦听 ...

  7. Asp.NetCore轻松学-使用Supervisor进行托管部署

    前言 上一篇文章 Asp.NetCore轻松学-部署到 Linux 进行托管 介绍了如何在 Centos 上部署自托管的 .NET Core 应用程序,接下来的内容就是介绍如何使用第三方任务管理程序来 ...

  8. Asp.NetCore轻松学-部署到 IIS 进行托管

    前言 经过一段时间的学习,终于来到了部署服务这个环节,.NetCore 的部署方式非常的灵活多样,但是其万变不离其宗,所有的 Asp.NetCore 程序都基于端口的侦听,在部署的时候仅需要配置侦听地 ...

  9. asp.netcore 深入了解配置文件加载过程

    前言     配置文件中程序运行中,担当着不可或缺的角色:通常情况下,使用 visual studio 进行创建项目过程中,项目配置文件会自动生成在项目根目录下,如 appsettings.json, ...

随机推荐

  1. Android Studio升级到0.8.1后怎样设置字体大小?

    升级到0.8.1后.打开设置字体大小页面.你会发现无论是Default还是Darcula,都不同意你改变字体的大小.事实上这个是由于这两个模式是Android Studio自带模式,所以不同意你修改, ...

  2. JAVA多态学习2

    好啦,这里紧接着上次没说的向下转型,请读者结合上次讨论的向上转型的样例一起探讨(事实上本次代码也有加上,放心). 我们这里希望从向下转型会出现的两种基本情况进行探讨 package downcasti ...

  3. Es61

    ECMAScript和JavaScript的关系 ECMAScript 6(以下简称ES6)是JavaScript语言的下一代标准,已经在2015年6月正式发布了.Mozilla公司将在这个标准的基础 ...

  4. elasticsearch index之Translog

    跟大多数分布式系统一样,es也通过临时写入写操作来保证数据安全.因为lucene索引过程中,数据会首先据缓存在内存中直到达到一个量(文档数或是占用空间大小)才会写入到磁盘.这就会带来一个风险,如果在写 ...

  5. VMwarep挂载镜像及配置本地Yum源

    1.挂载镜像: *. 通过mount命令         linux mount挂载设备(u盘,光盘,iso等 )使用说明 *.  通过VMware的控制页面手工挂载 1.1    打开Vmware软 ...

  6. 从excel 获取内容 模块:xlrd

    import xlrd # 获取表的对象 excel = xlrd.open_workbook(‘a.excel’) # 获取所有excel里的所有表 table_list = excel.sheet ...

  7. 【Uva 1633】Dyslexic Gollum

    [Link]: [Description] 输入正整数n和k(1≤n≤400,1≤k≤10),求长度为n的01串中有多少个不含长度至少 为k的回文连续子串.例如,n=k=3时只有4个串满足条件:001 ...

  8. 【MongoDB】mongodump and mongorestore of mogodb

    The another tool will be mentioned in this blog, namely mongodump and mongorestore. General speaking ...

  9. hdu 1233 还是畅通project (克鲁斯卡尔裸题)

    还是畅通project                                              Time Limit: 4000/2000 MS (Java/Others)    M ...

  10. 【JEECG技术博文】JEECG 简单实例解说权限控制

    JEECG简单实例解说权限控制 请大家点击这里为我们投票.2015博客之星.很多其他分享敬请期待 博文地址:http://blog.itpub.net/30066956/viewspace-18687 ...