ASP.NET Core 奇淫技巧之伪属性注入 (2)

Controller 的实现较为特殊,Controller 默认是不会通过自带容器来 Resolve&Activate 的,是通过MVC自身管理的,但是微软提供了这样的方法:

services.AddControllers().AddControllersAsServices();

可以通过调用 AddControllersAsServices() 方法来让 Controller 使用自带容器,其主要源代码如下

1585673407205

根据第四小节的思想,我们需要 Controller Resolve 时,来对属性进行赋值,那么我们需要改造 Controller 激活器。

定义 Controller 基类

1585673817076

Controller 继承基类

1585673605165

改造 Controller 激活器

1585673898053

可以看到我们改造的代码也就几行。

替换默认 Controller 激活器

services.AddControllers().AddControllersAsServices(); services.Replace(ServiceDescriptor.Transient<IControllerActivator, XcServiceBasedControllerActivator>()); //替换默认 Controller 激活器

运行测试

1585674115498

测试正常,如需其他属性的“属性注入”,参考日志这样做就行了。

六. 为 Application Service 实现伪属性注入

只是以 Application Service 来作为讲解,同理可举一反三到其他地方。Application Service 属于领域驱动分层架构中的一层,如不了解,可自行查找资料。

定义应用服务基类接口

public interface IAppService { ILogger Logger { get; set; } } public class AppService:IAppService { public ILogger Logger { get; set; } }

定义具体服务,以 User 服务为例

public interface IUserAppService:IAppService { void Create(); } public class UserAppService : AppService,IUserAppService { public void Create() { Logger.LogInformation("来自 Application Service 的日志"); } }

定义特殊的注册服务的方法,以便实现 Resolve 为 Logger 赋值

public static class ServiceExtensions { public static IServiceCollection AddApplicationService<TService, TImpl>(this IServiceCollection services) where TService:IAppService where TImpl:AppService { services.AddApplicationService(typeof(TService), typeof(TImpl)); return services; } // 可以反射程序集调用此方法实现批量自动注册应用服务 public static IServiceCollection AddApplicationService(this IServiceCollection services, Type serviceType,Type implType) { services.AddTransient(serviceType, sp => { //获取服务实现的实例 var implInstance = ActivatorUtilities.CreateInstance(sp, implType); ; if (implInstance is AppService obj) { //为 Logger 赋值 obj.Logger= sp.GetRequiredService<ILoggerFactory>().CreateLogger(implType); } return implInstance; }); return services; }

注册测试服务

1585675259627

Controller 注入测试服务

1585675328416

运行测试

1585675427275

七.结束

其实到本文写完,我都在想,要不要封装一个组件,发布到 Nuget 来方便的使用文中我所描述的“伪属性注入”,最后反复想了想,还是觉得不做。如果要使用完全的属性注入可以替换使用第三方容器,本文所述旨在不想引入第三方容器,且想在部分地方来达到属性注入的效果,因为属性注入这个东西也不推荐大范围使用。

本文来源于我在工作中的一些灵感总结,我在看 ControllerActivator 源码时的突发奇想,最近工作虽然忙,但是知识确实积攒了不少,在后面与大家一一分享。

姊妹篇:ASP.NET Core 奇淫技巧之动态WebApi

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wpjxsf.html