Controller 的实现较为特殊,Controller 默认是不会通过自带容器来 Resolve&Activate 的,是通过MVC自身管理的,但是微软提供了这样的方法:
services.AddControllers().AddControllersAsServices();可以通过调用 AddControllersAsServices() 方法来让 Controller 使用自带容器,其主要源代码如下
根据第四小节的思想,我们需要 Controller Resolve 时,来对属性进行赋值,那么我们需要改造 Controller 激活器。
定义 Controller 基类
Controller 继承基类
改造 Controller 激活器
可以看到我们改造的代码也就几行。
替换默认 Controller 激活器
services.AddControllers().AddControllersAsServices(); services.Replace(ServiceDescriptor.Transient<IControllerActivator, XcServiceBasedControllerActivator>()); //替换默认 Controller 激活器运行测试
测试正常,如需其他属性的“属性注入”,参考日志这样做就行了。
六. 为 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; }注册测试服务
Controller 注入测试服务
运行测试
七.结束其实到本文写完,我都在想,要不要封装一个组件,发布到 Nuget 来方便的使用文中我所描述的“伪属性注入”,最后反复想了想,还是觉得不做。如果要使用完全的属性注入可以替换使用第三方容器,本文所述旨在不想引入第三方容器,且想在部分地方来达到属性注入的效果,因为属性注入这个东西也不推荐大范围使用。
本文来源于我在工作中的一些灵感总结,我在看 ControllerActivator 源码时的突发奇想,最近工作虽然忙,但是知识确实积攒了不少,在后面与大家一一分享。
姊妹篇:ASP.NET Core 奇淫技巧之动态WebApi