是空裁。 是空空荡荡,却嗡嗡作响,谁在你心里放冷枪

唐僧团队要裁员,你会裁谁?_王学明

是空裁

序言: 远程工作已经一个月了,最近也算是比较闲,每天早上起床打个卡,快速弄完当天要做的工作之后就快乐摸鱼去了。 之前在用 (旧版)的时候就觉得应用服务层写起来真的爽,为什么实现了个 IApplicationService 的空接口就可以变成 Web API,可惜的是之前一直没空去研究这一块的原理及其实现,园子里也找不到相关实现原理的文章(旧版 ABP 的倒是有,但是 asp. net core 无法参考)。 最近闲起来,就看了一下 的源码,并且也参考了一下 介绍的。 我自己也简单实现了一遍动态 Web API,不禁感叹 asp. net core 设计之精妙。 abp vnext: Panda. DynamicWebApi: 这里先感谢这两个库的相关人员,没有他们的工作,本文也出现不了。 另外在此声明,本文意在探究其实现原理并实现一个简易版本,若无把握请勿用于生产环境。 正文: 首先先创建我们的解决方案如下: 因为动态 Web API 这一功能是与业务无关的,而且为了复用,我们应该把这一功能的实现写到一个单独的类库当中。 上图中 Demo 项目是 asp. net core 3. 1 版本的 Web API 项目,用于演示我们的简易动态 Web API,而 SimpleDynamicWebAPI 的. net standard 2. 0 项目则是我们的简易动态 Web API 项目。 要实现动态 Web API,首先要做的第一件事情就是要有一个规则,来判定一个类是不是动态 Web API。 在 abp vnext 当中, 主要提供两种方式,(实际开发过程中一般都是实现 ),。 而在 Panda. DynamicWebApi 中,则是。 因为本文是要实现简易版本,因此只选空接口方式。 net core 框架它是不知道的,我们需要把这个规则告诉它。 这一块 abp vnext 有点复杂,我们参考 Panda. DynamicWebAPI 的实现: 上面图中 DynamicWebApiControllerFeatureProvider 的 IsController 方法很明显了。 查看 : 粗俗点翻译过来就是判断一个类是不是控制器。 接下来开始依样画葫芦。 首先一点 类是属于 asp. net core 的,理论上是位于 这个 nuget 包的,但是这个包的 3. x 版本并没有发布在 nuget 上。 如果我们的 SimpleDynamicWebAPI 引用 2. x 版本的,而 Demo 项目又是 3. x 版本的,则很可能会引起冲突。 保险起见,我们 修改 SimpleDynamicWebAPI 为一个 asp. net core 的类库。 反正这个库本来也不可能会被其它类型诸如 WPF 的项目引用。 修改 SimpleDynamicWebAPI. csproj 如下: using Microsoft. AspNetCore. Mvc. Controllers; using System. typeInfo. typeInfo. typeInfo. 接下来,1、如果一个接口即使它实现了 IApplicationService,但它仍然不能是一个控制器,那是因为接口是无法实例化的;2、抽象类同理,也是因为无法实例化;3、泛型类也不允许,因为需要确切的类型才能实例化;4、public 代表着公开,可被外界访问,如果一个类不是 public 的,那么就不应该成为一个动态 Web API 控制器。 接下来就是要把这个 ApplicationServiceControllerFeatureProvider 加入到 asp. net core 框架中。 创建 SimpleDynamicWebApiExtensions 扩展类,修改代码如下: using Microsoft. Extensions. FeatureProviders. FeatureProviders. 当然参照 abp vnext 或 Panda. DynamicWebApi 从 services 中获取 ApplicationPartManager 对象实例也是可行的。 AddControllers. 但仅仅这样并不足够,假设有多个类同时实现 IApplicationService 接口,那应该如何映射呢,如果没错的话,这个时候你应该会想到是—— 路由。 我们还需要做的工作就是把这些控制器与路由配置起来。 abp vnext 这块为了在配置过程中获取 services 而延迟加载导致包了一层,有点复杂。 这里参考 Panda. DynamicWebApi 注释告诉了我们这里是配置控制器的路由,感谢作者大大。 继续画葫芦,创建 ApplicationServiceConvention 类并实现 接口: using Microsoft. AspNetCore. Mvc. net core 框架,修改 SimpleDynamicWebApiExtensions 扩展类如下: using Microsoft. AspNetCore. Mvc; using Microsoft. Extensions. FeatureProviders. Services. Conventions. FeatureProviders. Services. Conventions. ok,接下来回到考虑 Apply 方法实现的问题了。 这里参考 abp vnext: 上图中的 ApplyForControllers 方法的方法体关键部分很好懂,foreach 遍历了所有的控制器,如果控制器实现了 IRemoteService 接口或者标记了 RemoteServiceAttribute,则调用 ConfigureRemoteService 进一步处理。 因为我们的简易版本是只有接口,else 部分的我们就不需要了。 修改 ApplicationServiceConvention 代码如下: using Microsoft. AspNetCore. Mvc. IsAssignableFrom controller. 1、ConfigureApiExplorer。 ApiExplorer,简单点说就是 API 是否可被发现。 举个栗子,加入你写了一个 Web API,项目又配置了 swagger,而且你又想 swagger 不显示这个 Web API 的话,那么可以在 Action 上加上: using Microsoft. AspNetCore. Mvc. IsAssignableFrom controller. controller. ApiExplorer. IsVisible. ApiExplorer. action. ApiExplorer. IsVisible. ApiExplorer. 接下来 ConfigureSelector 看 abp vnext 的实现: 首先第一行 RemoveEmptySelectors 这是一个关键点。 虽然我们的动态 Web API 控制器一开始并没有配置路由,但实际上 asp. net core 框架会为此生成一些空白信息。 abp vnext 在这里就抹除掉了这些空白信息。 而 Panda. DynamicWebApi 虽然没有这样干,但是后面的判断逻辑就相对复杂了一些(大大别打我)。 ActionConstraints. EndpointMetadata. if 第一行明显可以看出判断路由信息是否存在,第二行判断的 Action 的约束,而约束则是指 HttpGet、HttpPost 这种约束,第三行判断了端点元数据信息,例如标记了什么 Attribute 之类的。 假如这些都没有,那么这条 selector 就可以断定为空白信息了。 接下来回到 abp vnext 代码截图的 181 行: 假如移除过空白信息后仍然有路由的话,则后续不进行处理。 接下来的 foreach 就开始处理 Action 了。 先完善我们的代码,再开始处理 Action 的路由: using Microsoft. AspNetCore. Mvc. ApplicationModels; using System; using System. Collections. Generic; using System. IsAssignableFrom controller. controller. ApiExplorer. IsVisible. ApiExplorer. action. ApiExplorer. IsVisible. ApiExplorer. Selectors ; if controller. Selectors. AttributeRouteModel! ActionConstraints. EndpointMetadata. 关键在最后的判断,假如没有 selector 的话,加上就是了。 但是如果已经有了呢?那就修改呗。 举个栗子,假如我们实现 IApplicationService 接口的类的一个方法标记了 HttpGet,那么这个 Action 是有约束的,但是它却是没有路由的。 这几行无论是 abp vnext 还是 Panda. DynamicWebApi 都是一样的。 ActionConstraints. Selectors. 要计算路由,我们先举个栗子(嗯,第三颗栗子了)。 Controller. ControllerName; if controllerName. Substring 0, controllerName. Length - " ApplicationService ". Substring 0, controllerName. Length - " AppService ". Parameters. ActionName; if actionName. Substring 0, actionName. Length - " Async ". Substring trimPrefix. string. 控制器部分,如果名字结尾是 ApplicationService 或者 AppService,那就裁掉。 并且变为复数。 因为这里是简易版,直接加 s 了是。 实际建议使用 等之类的库。 不然 bus 这种词直接加 s 就太奇怪了。 id 部分没啥好说的。 最后是 Action 部分,假如是 Async 结尾的,裁掉。 接下来看开头是不是以 Get、Post、Create 等等这些开头,是的话也裁掉, 注意要先判断 GetAll 和 GetList 然后再判断 Get。 因为最后裁掉之后有可能是空字符串,所以还需要判断一下再确定是否添加到路由中。 ActionName; if actionName. StartsWith " Put " actionName. StartsWith " Delete " actionName. ActionConstraints. OfType. FirstOrDefault?. HttpMethods?. ActionConstraints. 现在我们的 ApplicationServiceConvention 的代码应该如下: using Microsoft. AspNetCore. Mvc; using Microsoft. AspNetCore. Mvc. ActionConstraints; using Microsoft. AspNetCore. Mvc. ApplicationModels; using System; using System. Collections. Generic; using System. Linq; using System. IsAssignableFrom controller. controller. ApiExplorer. IsVisible. ApiExplorer. action. ApiExplorer. IsVisible. ApiExplorer. Selectors ; if controller. Selectors. AttributeRouteModel! Selectors ; if action. Selectors. Count. FirstOrDefault?. HttpMethods?. ActionConstraints. ActionConstraints. Selectors. Controller. ControllerName; if controllerName. Substring 0, controllerName. Length - " ApplicationService ". Substring 0, controllerName. Length - " AppService ". Parameters. ActionName; if actionName. Substring 0, actionName. Length - " Async ". Substring trimPrefix. string. ActionName; if actionName. StartsWith " Put " actionName. StartsWith " Delete " actionName. ActionConstraints. Count 、Nullable、DateTime 这些也不应该加 FromBody 绑定。 这个阅读 还是很好懂的。 第二个判断则判断了当前 Http 约束是否能用 FormBody,例如 GET、DELETE 请求是没办法用 FromBody 的。 BindingInfo! ParameterType. ParameterType! ParameterType! Selectors. ActionConstraints. OfType. HttpMethods. ToList ; if httpMethods. Contains " GET " httpMethods. Contains " DELETE " httpMethods. Contains " TRACE " httpMethods. 第二个判断则把 Http 约束通通查出来,如果有 GET、DELETE 等等这些则不能加 FromBody 约束,反之则加上。 演示: 历经千辛万苦,我们的简易版动态 Web API 终于完成了。 接下来我们可以给 Demo 项目添加一下测试代码以及配置 swagger 来看一下效果。 在 Demo 项目中添加测试代码 PersonAppService: using SimpleDynamicWebAPI; using System. Collections. Generic; using System. Linq; namespace Demo. ToCharArray. 完事之后跑起来。 感觉还行。 结语: 我们总算实现了一个非常简易的动态 Web API,也相当于又造了一遍轮子,但在这造轮子的过程中,我们了解到了其实现的原理,假如以后发现 abp vnext 等框架的动态 Web API 满足不了我们的时候,我们也有一定能力进行修改。 最后我再次声明,如果没有把握的话,千万别用于生产环境。 abp vnext 这种是经过大量项目验证的,即使有 bug,abp vnext 官方也有足够人力去修复。 最后附上 Gayhub 源码:.

次の

原来谢娜牵的是肖战空袖子!不愧是“绅士战”,张杰可以安心了_春晚

是空裁

然而,肖战和谢娜在春晚后台转场时的一组视频,引发了网友的热议。 镜头里的肖战一身修裁得体的纯红色西装,喜庆中又带着简洁端正。 和肖战并肩而行的谢娜,也是身着火红色V领包臀曳地长裙,缀以星星闪闪的碎钻,看上起贵气十足。 两人应该是刚刚离开春晚采访区的演播厅,一边走一边有说有笑,而且谢娜一只手捞着裙摆,另一手似乎在牵着肖战,看上去十分亲密。 再加上此前肖战还曾伸出一只胳膊,让谢娜的手指牵着他的袖角,既展现了足够的风度,还保持着礼貌距离。 所以,尽管肖战和谢娜在春晚舞台上扮演的是一对情侣,但是观众都清楚地知道,两人姐弟关系好但也不越矩,粉丝和张杰都很放心。 但是春晚的机会对于像肖战这般的年轻演员来说,无疑是一种莫大的鼓励和认可,让他可以很好地提高知名度和路人缘,因为春晚的语言类节目后期的重播率也是很高的。 从鼠年春晚过后的各项指数也可以得到印证,由谢娜、肖战、鞠婧祎、杨迪主演的小品《喜欢你喜欢我》以43. 他能做到不止步于前,大胆突破勇于冒险,希望在不同的领域挑战自己,又争取做到极致,做到更好,相信如此进取的肖战未来的星路也会越走越坦荡。 责任编辑:.

次の

是空空荡荡,却嗡嗡作响,谁在你心里放冷枪

是空裁

2 Pixel Depth变化 用不规则矢量多边形裁切栅格数据时,Extract by Mask对话框中没有提供设置Nodata的选项,这导致有时会出现裁剪后的pixel depth由原来的8bit变成了16bit 如下图2所示。 解决方法为在arctoolbox中使用栅格计算器工具,运用setnull命令将选定 个数最少的那类象元值 的值 如0值 设为nodata,然后再裁剪。 3 黑边处理 在栅格数据中,除了符合比特深度 Pixel Depth 的值之外,用于标记此处Nodata的值----就是空值。 产生空值的原因有很多种,有可能是在数据采集的时候,传感器没有记录下某个位置的反射值,或者是由于噪声。 用Identify工具查看黑边所示的像元值,通常会发现用0或者极小值来标记Nodata,而在ArcGIS中0值是一个有效值而不是空值。 出于这个原因,在渲染这类影像的时候,ArcGIS会将0值渲染成黑色,而不是作为空值处理成透明色。 那么我们如何消除这个黑边的问题呢? 在ArcGIS中,我们可以在图层属性Symbology页下看到这样的一个设置:Display Background value…as…。 通过输入0,0,0,以及将颜色设置成透明,就可以达到让黑边消失的渲染效果。 以上黑边处理是对单一的栅格数据,在实际应用中有时会遇到Mosaic Dataset这种数据模型,ArcGIS中提供了一个解决Mosaic Dataset中黑边问题的工具Define Mosaic DatasetNoData。 在工具中可以对每一个波段单独设置空值,完成后也可以得到理想的黑边变透明的效果。 然而以上处理并没有从根本上裁切掉那些黑边,要从根本上解决问题可以通过导出的方式将黑边设置为空。 具体操作就是在Export Data的时候,在NoData的选项中输入0,0,0 如下图。 看似问题得到了解决,然而这种做法会将影像中那些本来就是0值的像元也抹掉,所以这个办法要慎用。 那么目前有没有既有效又彻底的方法来解决不规则矢量多边形裁切栅格数据时出现的上述问题呢,答案依然是裁剪,接下来介绍栅格处理中的裁剪方法。 在Clip对话框中输入待裁切的栅格数据以及矢量多边形数据等参数,直接点击OK即可完成裁剪。 通常输入矢量多边形时,系统会自动获取该矢量多边形的最小外包矩形的范围作为实际裁剪的区域,而我们只需要勾选Use Input Features forCliping Geometry Optional 选项 如下图所示 就可以保证裁剪出来的栅格区域就是我们真正想要的。 同时还需要注意的是,Clip对话框中同样还提供了Nodata Value选项,我们可以将那些需要设置为空值的像元过滤掉。 通过对比以上两种矢量裁切方法,我们发现栅格处理中的裁剪方法既简单又有效。 对于习惯用Extraction by Mask方法的用户来说,与其舍近求远不如直接用Data Management Tool中的Clip工具。

次の