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. nowcoder 181045 / 克洛涅的多项式 构造+思维

    题意:有多项式 $F(x),G(x)$,最高次项分别为 $n,m$.$F(x)$ 最高次项系数为 $1$. $m<n$ 给定 $n$ 个不同的点值,满足 $F(x[i])=G(x[i])$ 给定 ...

  2. CF1051D Bicolorings 递推

    考试T2,随便推一推就好了~ code: #include <bits/stdc++.h> #define N 1015 #define mod 998244353 #define ll ...

  3. [luogu] 斐波那契数列

    https://www.luogu.org/problemnew/show/P1962 矩阵快速幂加速 #include <bits/stdc++.h> using namespace s ...

  4. NetworkX系列教程(2)-graph生成器

    小书匠Graph图论 本节主要讲解如何快速使用内置的方法生成graph,官方的文档在这里,里面包含了networkX的所有graph生成器,下面的内容只是我节选的内容,并将graph画出来而已. 声明 ...

  5. Centos 7 安装 Haproxy

    [环境] Centos 7.2 Web1:192.168.136.170 web2:192.168.136.166 Haproxy:192.168.136.173 [web服务器1.2] 安装Ngin ...

  6. (5)打鸡儿教你Vue.js

    条件与循环 条件判断使用 v-if 指令 <p v-if="seen"> <template v-if="ok"> <script ...

  7. 第四组团队git现场编程实战

    组员职责分工 组员 分工 林涛(组长) 分配任务.整理数据.写博客 童圣滔 UI界面制作 林红莲 UI界面制作 潘雨佳 测评出福州最受欢迎的商圈 于瀚翔 测评出福州最受欢迎的商圈 覃鸿浩 测评出福州人 ...

  8. spring + spring mvc 使用 maven 编译出现异常

    异常如下: [INFO] Scanning for projects...[INFO] [INFO] ------------------------------------------------- ...

  9. Effective Java 3

    <Effective Java>作者是美国的Joshua Bloch,连Gosling都说需要看的书,讨论的是更深层次的Java开发技术,适合于有一定Java基础的人看. 这是一本分享经验 ...

  10. Seata 中类SPI使用机制分析

    Seata中采用了与sofa-rpc和dubbo中相同的服务扩展机制.都是基于JAVA自身的服务发现机制-SPI进行再次封装注解,sofa-rpc和dubbo(@Deprecated)中的注解名字叫做 ...