FromServices回来
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回来的更多相关文章
- Asp.NETCore让FromServices回来
起因 这两天,我忽然有点怀念 Asp.NET MVC 5 之前的时代,原因是我看到项目里面有这么一段代码(其实不止一段,几乎每个 Controller 都是) [Route("home&qu ...
- Android 打开方式选定后默认了改不回来?解决方法(三星s7为例)
Android 打开方式选定后默认了改不回来?解决方法(三星s7为例) 刚刚在测试东西,打开一个gif图,然后我故意选择用支付宝打开,然后...支付宝当然不支持,我觉得第二次打开它应该还会问我,没想到 ...
- [分享] 很多人手机掉了,却不知道怎么找回来。LZ亲身经历讲述手机找回过程,申请加精!
文章开头:(LZ文笔不好,以下全部是文字描述,懒得配图.因为有人说手机掉了,他们问我是怎么找回来的.所以想写这篇帖子.只不过前段时间忙,没时间.凑端午节给大家一些经验) 还是先谢谢被偷经历吧!5月22 ...
- 如何使用Retrofit获取服务器返回来的JSON字符串
有关Retrofit的简单集成攻略,大家可以参考我此前的一篇文章有关更多API文档的查阅请大家到Retrofit官网查看. 在大家使用网络请求的时候,往往会出现一种情况:需要在拿到服务器返回来的JSO ...
- cocos2dx shader实现灰度图android后台切换回来导致图像偏移的问题
转自:http://www.tuicool.com/articles/U3URRrI 项目中经常会遇到将一张图像处理成灰色的需求,为了节省资源,一般不会让美术再做一套同样的灰度图,通常会通过代码处理让 ...
- 我又回来了,这回是带着C++来的
一晃就是5年,之前在博客园开这个博客主要是跟着大牛学习C#,那个时候自己偏重于asp.net,后来开发了一段时间的Winform.近几年由于工作原因,偏重于测试仪器开发,属于工控行业,主要使用的是C+ ...
- Windows下如何检测用户修改了系统时间并且把系统时间改回来
博客搬到了fresky.github.io - Dawei XU,请各位看官挪步.最新的一篇是:Windows下如何检测用户修改了系统时间并且把系统时间改回来.
- Unity3D研究院之在把代码混淆过的游戏返混淆回来
最近一直在找如何在MAC上混淆Android的DLL,至今没能找到合适的,有大神知道记得告诉我喔.今天群里有人说了一个混淆代码和返混淆代码的工具de4dot ,不查不知道一查吓一跳.这玩意可以把别人混 ...
- Access中出现改变字段“自己主动编号”类型,不能再改回来!(已解决)
Access中出现改变字段"自己主动编号"类型,不能再改回来! (已解决) 一次把access中的自增字段改成了数值,再改回自增时,提示:在表中输入了数据之后,则不能将不论什么字段 ...
随机推荐
- Greenplum 查看连接与锁信息数据字典
查看系统中会话/连接/SQL与锁情况 1.查看当前活动的客户端连接数 SELECT count(*) FROM pg_stat_activity WHERE NOT pid=pg_backend_p ...
- 四十七.iptables防火墙 filter表控制 扩展匹配 nat表典型应用
1.iptables基本管理 关闭firewalld,开启iptables服务 查看防火墙规则 追加.插入防火墙规则 删除.清空防火墙规则 1.1 关闭firewalld,启动iptables服务 ...
- Jenkins automate workflow
Now we will build an automate flow from code compiling to product delivery.The essential tools using ...
- linux系列(八):cp命令
1.命令格式: cp [选项]... [-T] 源 目的 2.命令功能: 将源文件复制至目标文件,或将多个源文件复制至目标目录. 3.命令参数: -a:此参数的效果和同时指定"-dpR&qu ...
- 特征工程学习01-sklearn单机特征工程
特征工程学习01-sklearn单机特征工程 小书匠 kindle 0.数据的导入 from sklearn.datasets import load_iris #导入IRIS数据集 iris= ...
- geometry_msgs/PoseStamped 类型的变量的构造
#navpoint.msg geometry_msgs/PoseStamped target_pose uint8 floor uint8 type target_pose 的类型为geometry_ ...
- Java实现通过IP获取域名,通过域名获取IP
一.通过Linux命令实现 ping www.baidu.com nslookup www.baidu.com nslookup 14.215.177.166 为什么这个命令会有一个192.168.1 ...
- dubbo zookeeper图解入门配置
这次主要是对dubbo 和zookeeper的配置做个记录,以便以后自己忘记了,或者踩的坑再次被踩 快速阅读 zookeerer类似 springcloud中的Eureka都做为注册中心,用srpin ...
- JavaScript中获取html元素常用手法和区分
对于许多前端开发项目来说,获取元素进行操作是必不可少的,例如tab标签,全屏切换,自动滚播等效果都需要通过获取节点元素来实现.下面我来总结下JavaScript最常用的4个Document对象中获取元 ...
- vue 弹窗式 滑动图片验证码
效果图: 具体代码: test.vue //整个页面是个弹窗 visible 控制弹窗的显示关闭 默认打开 <template> <div class="mask_laye ...