这样子下来,虽然功能实现了,但是里面存着几个问题。第一个是由于控制器的构造函数中不能直接使用ControllerBase的HttpContext属性,所以必须要通过注入IHttpContextAccessor对象来获取,貌似问题又回到原点。第二个是每个构造函数中都要写这么一堆代码,不能忍。于是想有没有办法在控制器被激活的时候做一些操作?没考虑引入AOP框架,感觉为了这一个功能引入AOP有点重。经过网上搜索,发现Asp.Net Core框架激活控制器是通过IControllerActivator接口实现的,它的默认实现是DefaultControllerActivator(https://github.com/aspnet/AspNetCore/blob/master/src/Mvc/Mvc.Core/src/Controllers/DefaultControllerActivator.cs):
/// <inheritdoc />
public object Create(ControllerContext controllerContext)
{
if (controllerContext == null)
{
throw new ArgumentNullException(nameof(controllerContext));
}
if (controllerContext.ActionDescriptor == null)
{
throw new ArgumentException(Resources.FormatPropertyOfTypeCannotBeNull(
nameof(ControllerContext.ActionDescriptor),
nameof(ControllerContext)));
}
var controllerTypeInfo = controllerContext.ActionDescriptor.ControllerTypeInfo;
if (controllerTypeInfo == null)
{
throw new ArgumentException(Resources.FormatPropertyOfTypeCannotBeNull(
nameof(controllerContext.ActionDescriptor.ControllerTypeInfo),
nameof(ControllerContext.ActionDescriptor)));
}
var serviceProvider = controllerContext.HttpContext.RequestServices;
return _typeActivatorCache.CreateInstance<object>(serviceProvider, controllerTypeInfo.AsType());
}
这样一来,我自己实现一个Controller激活器不就可以接管控制器激活了,于是有如下这个类:
public class HosControllerActivator : IControllerActivator
{
public object Create(ControllerContext actionContext)
{
var controllerType = actionContext.ActionDescriptor.ControllerTypeInfo.AsType();
var instance = actionContext.HttpContext.RequestServices.GetRequiredService(controllerType);
PropertyActivate(instance, actionContext.HttpContext.RequestServices);
return instance;
}
public virtual void Release(ControllerContext context, object controller)
{
if (context == null)
{
throw new ArgumentNullException(nameof(context));
}
if (controller == null)
{
throw new ArgumentNullException(nameof(controller));
}
if (controller is IDisposable disposable)
{
disposable.Dispose();
}
}
private void PropertyActivate(object service, IServiceProvider provider)
{
var serviceType = service.GetType();
var properties = serviceType.GetProperties().AsEnumerable().Where(x => x.Name.StartsWith("_"));
foreach (PropertyInfo property in properties)
{
var autowiredAttr = property.GetCustomAttribute<AutowiredAttribute>();
if (autowiredAttr != null)
{
//从DI容器获取实例
var innerService = provider.GetService(property.PropertyType);
if (innerService != null)
{
//递归解决服务嵌套问题
PropertyActivate(innerService, provider);
//属性赋值
property.SetValue(service, innerService);
}
}
}
}
}








