FromServices回来

起因

这两天,我忽然有点怀念 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

FromServices回来的更多相关文章

  1. Asp.NETCore让FromServices回来

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

  2. Android 打开方式选定后默认了改不回来?解决方法(三星s7为例)

    Android 打开方式选定后默认了改不回来?解决方法(三星s7为例) 刚刚在测试东西,打开一个gif图,然后我故意选择用支付宝打开,然后...支付宝当然不支持,我觉得第二次打开它应该还会问我,没想到 ...

  3. [分享] 很多人手机掉了,却不知道怎么找回来。LZ亲身经历讲述手机找回过程,申请加精!

    文章开头:(LZ文笔不好,以下全部是文字描述,懒得配图.因为有人说手机掉了,他们问我是怎么找回来的.所以想写这篇帖子.只不过前段时间忙,没时间.凑端午节给大家一些经验) 还是先谢谢被偷经历吧!5月22 ...

  4. 如何使用Retrofit获取服务器返回来的JSON字符串

    有关Retrofit的简单集成攻略,大家可以参考我此前的一篇文章有关更多API文档的查阅请大家到Retrofit官网查看. 在大家使用网络请求的时候,往往会出现一种情况:需要在拿到服务器返回来的JSO ...

  5. cocos2dx shader实现灰度图android后台切换回来导致图像偏移的问题

    转自:http://www.tuicool.com/articles/U3URRrI 项目中经常会遇到将一张图像处理成灰色的需求,为了节省资源,一般不会让美术再做一套同样的灰度图,通常会通过代码处理让 ...

  6. 我又回来了,这回是带着C++来的

    一晃就是5年,之前在博客园开这个博客主要是跟着大牛学习C#,那个时候自己偏重于asp.net,后来开发了一段时间的Winform.近几年由于工作原因,偏重于测试仪器开发,属于工控行业,主要使用的是C+ ...

  7. Windows下如何检测用户修改了系统时间并且把系统时间改回来

    博客搬到了fresky.github.io - Dawei XU,请各位看官挪步.最新的一篇是:Windows下如何检测用户修改了系统时间并且把系统时间改回来.

  8. Unity3D研究院之在把代码混淆过的游戏返混淆回来

    最近一直在找如何在MAC上混淆Android的DLL,至今没能找到合适的,有大神知道记得告诉我喔.今天群里有人说了一个混淆代码和返混淆代码的工具de4dot ,不查不知道一查吓一跳.这玩意可以把别人混 ...

  9. Access中出现改变字段“自己主动编号”类型,不能再改回来!(已解决)

    Access中出现改变字段"自己主动编号"类型,不能再改回来! (已解决) 一次把access中的自增字段改成了数值,再改回自增时,提示:在表中输入了数据之后,则不能将不论什么字段 ...

随机推荐

  1. [TJOI2015]弦论(第k小子串)

    题意: 对于一个给定的长度为n的字符串,求出它的第k小子串. 有参数t,t为0则表示不同位置的相同子串算作一个,t为1则表示不同位置的相同子串算作多个. 题解: 首先,因为t的原因,后缀数组较难实现, ...

  2. HTML 001 入门介绍

    HTML 教程- (HTML5 标准) 超文本标记语言(英语:HyperText Markup Language,简称:HTML)是一种用于创建网页的标准标记语言. 您可以使用 HTML 来建立自己的 ...

  3. Laradock Laravel database connection refused

    Laradock Laravel database connection refused SHARE  Laradock is a PHP development environment which ...

  4. 爬虫(十五):scrapy中的settings详解

    Scrapy设定(settings)提供了定制Scrapy组件的方法.你可以控制包括核心(core),插件(extension),pipeline及spider组件.设定为代码提供了提取以key-va ...

  5. vue中router-link的详细用法

    官网文档地址:https://router.vuejs.org/zh/api/#to 今天项目突然有需求,让vue中的一个页面跳转到另一个页面 // 字符串 <router-link to=&q ...

  6. php des 对称加解密类

    <?php header("Content-Type: text/html;charset=utf-8"); /** * des 对称加解密 */ class des { p ...

  7. 遇到bug如何处理

    issue中查询是否有相似bug assert / try-except / IDE单步调式 框架可以查询源码或者查询官方文档

  8. js 删除节点

    亲身经历,寻得此法,告知大家=============== 在javascript操作dom树的时候可能会经常遇到增加,删除节点的事情,比如一个输入框后一个增加按钮,一个删除按钮,点击增加就增加 个输 ...

  9. 网DAI之家简单爬取

    用requests和bs做个简单的爬取网DAI之家的例子. 只做笔记用. #!/usr/bin/python3 import requestsfrom bs4 import BeautifulSoup ...

  10. Vue中的动画效果

    Vue 在插入.更新或者移除 DOM 时,提供多种不同方式的应用过渡效果.包括以下工具: 在 CSS 过渡和动画中自动应用 class 可以配合使用第三方 CSS 动画库,如 Animate.css ...