Asp.net web Api源码分析-HttpControllerDispatcher (Controller的创建)
2012-12-04 16:36
645 查看
紧接着上文Asp.net web Api源码分析-HttpServer的创建最后我们提到了一个HttpRoutingDispatcher,一看这个类的名字我想我们也就能猜到它是干什么的吧。查找路由信息,那么找到路由后干什么了,是不是就该调用handler了?
首先还是让我们来看看HttpRoutingDispatcher的SendAsync方法
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
// Lookup route data, or if not found as a request property then we look it up in the route table
IHttpRouteData routeData;
if (!request.Properties.TryGetValue(HttpPropertyKeys.HttpRouteDataKey, out routeData))
{
routeData = _configuration.Routes.GetRouteData(request);
if (routeData != null)
{
request.Properties.Add(HttpPropertyKeys.HttpRouteDataKey, routeData);
}
else
{
return TaskHelpers.FromResult(request.CreateErrorResponse(
HttpStatusCode.NotFound,
Error.Format(SRResources.ResourceNotFound, request.RequestUri),
SRResources.NoRouteData));
}
}
RemoveOptionalRoutingParameters(routeData.Values);
var invoker = routeData.Route.Handler == null ? _defaultInvoker : new HttpMessageInvoker(routeData.Route.Handler, disposeHandler: false);
return invoker.SendAsync(request, cancellationToken);
}
首先这里先从HttpRequestMessage中获取路由信息,如果不能获取则调用_configuration.Routes.GetRouteData来获取路由信息,默认情况下这里是可以获取到路由信息(因为在HttpControllerHandler的BeginProcessRequest方法中有这么一句 request.Properties[HttpPropertyKeys.HttpRouteDataKey] = _routeData;)然后调用RemoveOptionalRoutingParameters方法来移除路由中的可选参数。
这里的routeData我们知道它是在HttpControllerHandler的构造函数中创建的一个HostedHttpRouteData实例,其Route属性是一个HostedHttpRoute实例,routeData.Route.Handler就是我们路由中注册的handler,默认情况下我们没有注册自己的handler,所以这里的invoker=_defaultInvoker,这里的_defaultInvoker= new HttpMessageInvoker(new
HttpControllerDispatcher(configuration)),所以调用invoker的SendAsync方法,其实就是调用HttpControllerDispatcher的SendAsync方法。
HttpControllerDispatcher这个名称我们就可以猜测到它是把当前http请求交给特定的Controller来处理。HttpControllerDispatcher的SendAsync方法差不多就是一个内联函数,直接调用内部的SendAsyncInternal方法:
首先调用 IHttpRouteData routeData = request.GetRouteData();来获取路由信息,其主要实现代码如下:
所以这里的ControllerSelector属性其实是一个DefaultHttpControllerSelector实例。那么我们来看看DefaultHttpControllerSelector的SelectController方法吧:
string controllerName = GetControllerName(request);
HttpControllerDescriptor controllerDescriptor;
if (_controllerInfoCache.Value.TryGetValue(controllerName, out controllerDescriptor))
{
return controllerDescriptor;
}
这里首先是获取Controller的名称,GetControllerName方法的实现如下:
public virtual string GetControllerName(HttpRequestMessage request)
{
IHttpRouteData routeData = request.GetRouteData();
string controllerName = null;
routeData.Values.TryGetValue(ControllerKey, out controllerName);
return controllerName;
}
private const string ControllerKey = "controller";
我们知道这里的routeData是HostedHttpRouteData实例,那么它的Values是什么了,HostedHttpRouteData的Values如下
public IDictionary<string, object> Values
{
get { return OriginalRouteData.Values; }
}
这里的OriginalRouteData是真正的路由信息。
现在我们来看看_controllerInfoCache这个东东是什么时候这是的了?在DefaultHttpControllerSelector的构造函数中有如下代码:
public DefaultHttpControllerSelector(HttpConfiguration configuration)
{
if (configuration == null)
{
throw Error.ArgumentNull("configuration");
}
_controllerInfoCache = new Lazy<ConcurrentDictionary<string, HttpControllerDescriptor>>(InitializeControllerInfoCache);
_configuration = configuration;
_controllerTypeCache = new HttpControllerTypeCache(_configuration);
}
这里我们还是先看看_controllerTypeCache的设置吧,直接实例化一个HttpControllerTypeCache,而HttpControllerTypeCache的构造函数如下:
public HttpControllerTypeCache(HttpConfiguration configuration)
{
if (configuration == null)
{
throw Error.ArgumentNull("configuration");
}
_configuration = configuration;
_cache = new Lazy<Dictionary<string, ILookup<string, Type>>>(InitializeCache);
}
我们具体看看HttpControllerTypeCache的InitializeCache方法是如何实现的:
private Dictionary<string, ILookup<string, Type>> InitializeCache()
{
IAssembliesResolver assembliesResolver = _configuration.Services.GetAssembliesResolver();
IHttpControllerTypeResolver controllersResolver = _configuration.Services.GetHttpControllerTypeResolver();
ICollection<Type> controllerTypes = controllersResolver.GetControllerTypes(assembliesResolver);
var groupedByName = controllerTypes.GroupBy(
t => t.Name.Substring(0, t.Name.Length - DefaultHttpControllerSelector.ControllerSuffix.Length),
StringComparer.OrdinalIgnoreCase);
return groupedByName.ToDictionary(
g => g.Key,
g => g.ToLookup(t => t.Namespace ?? String.Empty, StringComparer.OrdinalIgnoreCase),
StringComparer.OrdinalIgnoreCase);
}
从DefaultServices的构造函数我们知道这里的assembliesResolver
是一个DefaultAssembliesResolver实例,controllersResolver
是一个DefaultHttpControllerTypeResolver实例,但是在GlobalConfiguration有这么一句config.Services.Replace(typeof(IHttpControllerTypeResolver), new WebHostHttpControllerTypeResolver());。其中DefaultAssembliesResolver的实现如下
public class DefaultAssembliesResolver : IAssembliesResolver
{
public virtual ICollection<Assembly> GetAssemblies()
{
return AppDomain.CurrentDomain.GetAssemblies().ToList();
}
}
}
它主要是获取所有的程序集,而DefaultHttpControllerTypeResolver的GetControllerTypes大致实现如下:
public virtual ICollection<Type> GetControllerTypes(IAssembliesResolver assembliesResolver)
{
List<Type> result = new List<Type>();
ICollection<Assembly> assemblies = assembliesResolver.GetAssemblies();
foreach (Assembly assembly in assemblies)
{
Type[] exportedTypes = null;
try
{
exportedTypes = assembly.GetExportedTypes();
}
catch (ReflectionTypeLoadException ex)
{
exportedTypes = ex.Types;
}
if (exportedTypes != null)
{
result.AddRange(exportedTypes.Where(x => IsControllerTypePredicate(x)));
}
}
return result;
}
这里的IsControllerTypePredicate主要是检查我们的type是否是一个ControllerType,它必须是一个可见的非抽象类,并且它实现了IHttpController接口,且类名必须以Controller结尾。
所以HttpControllerTypeCache的InitializeCache方法返回了一个以Controller名称为key的字典。
现在轮到我们的WebHostHttpControllerTypeResolver了,
internal sealed class WebHostHttpControllerTypeResolver : DefaultHttpControllerTypeResolver
{
public override ICollection<Type> GetControllerTypes(IAssembliesResolver assembliesResolver)
{
HttpControllerTypeCacheSerializer serializer = new HttpControllerTypeCacheSerializer();
// First, try reading from the cache on disk
List<Type> matchingTypes = ReadTypesFromCache(TypeCacheName, IsControllerTypePredicate, serializer);
if (matchingTypes != null)
{
return matchingTypes;
}
// If reading from the cache failed, enumerate over every assembly looking for a matching type
matchingTypes = base.GetControllerTypes(assembliesResolver).ToList();
// Finally, save the cache back to disk
SaveTypesToCache(TypeCacheName, matchingTypes, serializer);
return matchingTypes;
}
}
现在我们有回到DefaultHttpControllerSelector的构造方法中来,这里的_controllerTypeCache已经明白是怎么一回事了,我们该来看看DefaultHttpControllerSelector的InitializeControllerInfoCache是怎么实现的。
private ConcurrentDictionary<string, HttpControllerDescriptor> InitializeControllerInfoCache()
{
var result = new ConcurrentDictionary<string, HttpControllerDescriptor>(StringComparer.OrdinalIgnoreCase);
var duplicateControllers = new HashSet<string>();
Dictionary<string, ILookup<string, Type>> controllerTypeGroups = _controllerTypeCache.Cache;
foreach (KeyValuePair<string, ILookup<string, Type>> controllerTypeGroup in controllerTypeGroups)
{
string controllerName = controllerTypeGroup.Key;
foreach (IGrouping<string, Type> controllerTypesGroupedByNs in controllerTypeGroup.Value)
{
foreach (Type controllerType in controllerTypesGroupedByNs)
{
if (result.Keys.Contains(controllerName))
{
duplicateControllers.Add(controllerName);
break;
}
else
{
result.TryAdd(controllerName, new HttpControllerDescriptor(_configuration, controllerName, controllerType));
}
}
}
}
foreach (string duplicateController in duplicateControllers)
{
HttpControllerDescriptor descriptor;
result.TryRemove(duplicateController, out descriptor);
}
return result;
}
这个方法就很简单了,我也不多说了,主要是创建HttpControllerDescriptor实例,在HttpControllerDescriptor构造函数中调有一个Initialize方法来做一些初始化的工作,而它也主要调用InvokeAttributesOnControllerType方法,具体实现:
private static void InvokeAttributesOnControllerType(HttpControllerDescriptor controllerDescriptor, Type type)
{
InvokeAttributesOnControllerType(controllerDescriptor, type.BaseType);
object[] attrs = type.GetCustomAttributes(inherit: false);
foreach (object attr in attrs)
{
var controllerConfig = attr as IControllerConfiguration;
if (controllerConfig != null)
{
var originalConfig = controllerDescriptor.Configuration;
var controllerSettings = new HttpControllerSettings(originalConfig);
controllerConfig.Initialize(controllerSettings, controllerDescriptor);
controllerDescriptor.Configuration = HttpConfiguration.ApplyControllerSettings(controllerSettings, originalConfig);
}
}
}
由于默认情况下我们没有IControllerConfiguration特性所以这里这个也就忽略吧。到这里DefaultHttpControllerSelector中SelectController的_controllerInfoCache.Value.TryGetValue(controllerName, out controllerDescriptor)也就很好明白了。
现在我们回到HttpControllerDispatcher中SendAsyncInternal方法来,这里有
IHttpController httpController = httpControllerDescriptor.CreateController(request);,我们知道httpControllerDescriptor是一个HttpControllerDescriptor实例,它的CreateController方法如下:
public class HttpControllerDescriptor
{
public virtual IHttpController CreateController(HttpRequestMessage request)
{
IHttpControllerActivator activator = Configuration.Services.GetHttpControllerActivator();
IHttpController instance = activator.Create(request, this, ControllerType);
return instance;
}
}
从DefaultServices中我们可以知道这里的activator 是DefaultHttpControllerActivator实例,这里的DefaultHttpControllerActivator.Create方法实现非常复杂,里面涉及到表达式树。
现在我们回到HttpControllerDispatcher的SendAsyncInternal方法中来,现在IHttpController实例我们已经创建好了,然后创建HttpControllerContext实例,
HttpControllerContext controllerContext = new HttpControllerContext(httpControllerDescriptor.Configuration, routeData, request);
controllerContext.Controller = httpController;
controllerContext.ControllerDescriptor = httpControllerDescriptor;
最后调用IHttpController的ExecuteAsync方法,到这里我们才真正进入到controller的方法调用中来
首先还是让我们来看看HttpRoutingDispatcher的SendAsync方法
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
// Lookup route data, or if not found as a request property then we look it up in the route table
IHttpRouteData routeData;
if (!request.Properties.TryGetValue(HttpPropertyKeys.HttpRouteDataKey, out routeData))
{
routeData = _configuration.Routes.GetRouteData(request);
if (routeData != null)
{
request.Properties.Add(HttpPropertyKeys.HttpRouteDataKey, routeData);
}
else
{
return TaskHelpers.FromResult(request.CreateErrorResponse(
HttpStatusCode.NotFound,
Error.Format(SRResources.ResourceNotFound, request.RequestUri),
SRResources.NoRouteData));
}
}
RemoveOptionalRoutingParameters(routeData.Values);
var invoker = routeData.Route.Handler == null ? _defaultInvoker : new HttpMessageInvoker(routeData.Route.Handler, disposeHandler: false);
return invoker.SendAsync(request, cancellationToken);
}
首先这里先从HttpRequestMessage中获取路由信息,如果不能获取则调用_configuration.Routes.GetRouteData来获取路由信息,默认情况下这里是可以获取到路由信息(因为在HttpControllerHandler的BeginProcessRequest方法中有这么一句 request.Properties[HttpPropertyKeys.HttpRouteDataKey] = _routeData;)然后调用RemoveOptionalRoutingParameters方法来移除路由中的可选参数。
这里的routeData我们知道它是在HttpControllerHandler的构造函数中创建的一个HostedHttpRouteData实例,其Route属性是一个HostedHttpRoute实例,routeData.Route.Handler就是我们路由中注册的handler,默认情况下我们没有注册自己的handler,所以这里的invoker=_defaultInvoker,这里的_defaultInvoker= new HttpMessageInvoker(new
HttpControllerDispatcher(configuration)),所以调用invoker的SendAsync方法,其实就是调用HttpControllerDispatcher的SendAsync方法。
HttpControllerDispatcher这个名称我们就可以猜测到它是把当前http请求交给特定的Controller来处理。HttpControllerDispatcher的SendAsync方法差不多就是一个内联函数,直接调用内部的SendAsyncInternal方法:
private Task<HttpResponseMessage> SendAsyncInternal(HttpRequestMessage request, CancellationToken cancellationToken) { if (request == null) { throw Error.ArgumentNull("request"); } IHttpRouteData routeData = request.GetRouteData(); Contract.Assert(routeData != null); HttpControllerDescriptor httpControllerDescriptor = ControllerSelector.SelectController(request); if (httpControllerDescriptor == null) { return TaskHelpers.FromResult(request.CreateErrorResponse( HttpStatusCode.NotFound, Error.Format(SRResources.ResourceNotFound, request.RequestUri), SRResources.NoControllerSelected)); } IHttpController httpController = httpControllerDescriptor.CreateController(request); if (httpController == null) { return TaskHelpers.FromResult(request.CreateErrorResponse( HttpStatusCode.NotFound, Error.Format(SRResources.ResourceNotFound, request.RequestUri), SRResources.NoControllerCreated)); } // Set the controller configuration on the request properties HttpConfiguration requestConfig = request.GetConfiguration(); if (requestConfig == null) { request.Properties.Add(HttpPropertyKeys.HttpConfigurationKey, httpControllerDescriptor.Configuration); } else { if (requestConfig != httpControllerDescriptor.Configuration) { request.Properties[HttpPropertyKeys.HttpConfigurationKey] = httpControllerDescriptor.Configuration; } } // Create context HttpControllerContext controllerContext = new HttpControllerContext(httpControllerDescriptor.Configuration, routeData, request); controllerContext.Controller = httpController; controllerContext.ControllerDescriptor = httpControllerDescriptor; return httpController.ExecuteAsync(controllerContext, cancellationToken); }在这个方法里面主要是获取Controller,然后再执行它。
首先调用 IHttpRouteData routeData = request.GetRouteData();来获取路由信息,其主要实现代码如下:
public static IHttpRouteData GetRouteData(this HttpRequestMessage request) { if (request == null) { throw Error.ArgumentNull("request"); } return request.GetProperty<IHttpRouteData>(HttpPropertyKeys.HttpRouteDataKey); } private static T GetProperty<T>(this HttpRequestMessage request, string key) { T value; request.Properties.TryGetValue(key, out value); return value; } public static bool TryGetValue<T>(this IDictionary<string, object> collection, string key, out T value) { if (collection == null) { throw Error.ArgumentNull("collection"); } object valueObj; if (collection.TryGetValue(key, out valueObj)) { if (valueObj is T) { value = (T)valueObj; return true; } } value = default(T); return false; }然后调用 HttpControllerDescriptor httpControllerDescriptor = ControllerSelector.SelectController(request);来获取HttpControllerDescriptor实例,在DefaultServices类中有如下代码: SetSingle<IHttpControllerSelector>(new DefaultHttpControllerSelector(configuration));
所以这里的ControllerSelector属性其实是一个DefaultHttpControllerSelector实例。那么我们来看看DefaultHttpControllerSelector的SelectController方法吧:
string controllerName = GetControllerName(request);
HttpControllerDescriptor controllerDescriptor;
if (_controllerInfoCache.Value.TryGetValue(controllerName, out controllerDescriptor))
{
return controllerDescriptor;
}
这里首先是获取Controller的名称,GetControllerName方法的实现如下:
public virtual string GetControllerName(HttpRequestMessage request)
{
IHttpRouteData routeData = request.GetRouteData();
string controllerName = null;
routeData.Values.TryGetValue(ControllerKey, out controllerName);
return controllerName;
}
private const string ControllerKey = "controller";
我们知道这里的routeData是HostedHttpRouteData实例,那么它的Values是什么了,HostedHttpRouteData的Values如下
public IDictionary<string, object> Values
{
get { return OriginalRouteData.Values; }
}
这里的OriginalRouteData是真正的路由信息。
现在我们来看看_controllerInfoCache这个东东是什么时候这是的了?在DefaultHttpControllerSelector的构造函数中有如下代码:
public DefaultHttpControllerSelector(HttpConfiguration configuration)
{
if (configuration == null)
{
throw Error.ArgumentNull("configuration");
}
_controllerInfoCache = new Lazy<ConcurrentDictionary<string, HttpControllerDescriptor>>(InitializeControllerInfoCache);
_configuration = configuration;
_controllerTypeCache = new HttpControllerTypeCache(_configuration);
}
这里我们还是先看看_controllerTypeCache的设置吧,直接实例化一个HttpControllerTypeCache,而HttpControllerTypeCache的构造函数如下:
public HttpControllerTypeCache(HttpConfiguration configuration)
{
if (configuration == null)
{
throw Error.ArgumentNull("configuration");
}
_configuration = configuration;
_cache = new Lazy<Dictionary<string, ILookup<string, Type>>>(InitializeCache);
}
我们具体看看HttpControllerTypeCache的InitializeCache方法是如何实现的:
private Dictionary<string, ILookup<string, Type>> InitializeCache()
{
IAssembliesResolver assembliesResolver = _configuration.Services.GetAssembliesResolver();
IHttpControllerTypeResolver controllersResolver = _configuration.Services.GetHttpControllerTypeResolver();
ICollection<Type> controllerTypes = controllersResolver.GetControllerTypes(assembliesResolver);
var groupedByName = controllerTypes.GroupBy(
t => t.Name.Substring(0, t.Name.Length - DefaultHttpControllerSelector.ControllerSuffix.Length),
StringComparer.OrdinalIgnoreCase);
return groupedByName.ToDictionary(
g => g.Key,
g => g.ToLookup(t => t.Namespace ?? String.Empty, StringComparer.OrdinalIgnoreCase),
StringComparer.OrdinalIgnoreCase);
}
从DefaultServices的构造函数我们知道这里的assembliesResolver
是一个DefaultAssembliesResolver实例,controllersResolver
是一个DefaultHttpControllerTypeResolver实例,但是在GlobalConfiguration有这么一句config.Services.Replace(typeof(IHttpControllerTypeResolver), new WebHostHttpControllerTypeResolver());。其中DefaultAssembliesResolver的实现如下
public class DefaultAssembliesResolver : IAssembliesResolver
{
public virtual ICollection<Assembly> GetAssemblies()
{
return AppDomain.CurrentDomain.GetAssemblies().ToList();
}
}
}
它主要是获取所有的程序集,而DefaultHttpControllerTypeResolver的GetControllerTypes大致实现如下:
public virtual ICollection<Type> GetControllerTypes(IAssembliesResolver assembliesResolver)
{
List<Type> result = new List<Type>();
ICollection<Assembly> assemblies = assembliesResolver.GetAssemblies();
foreach (Assembly assembly in assemblies)
{
Type[] exportedTypes = null;
try
{
exportedTypes = assembly.GetExportedTypes();
}
catch (ReflectionTypeLoadException ex)
{
exportedTypes = ex.Types;
}
if (exportedTypes != null)
{
result.AddRange(exportedTypes.Where(x => IsControllerTypePredicate(x)));
}
}
return result;
}
这里的IsControllerTypePredicate主要是检查我们的type是否是一个ControllerType,它必须是一个可见的非抽象类,并且它实现了IHttpController接口,且类名必须以Controller结尾。
所以HttpControllerTypeCache的InitializeCache方法返回了一个以Controller名称为key的字典。
现在轮到我们的WebHostHttpControllerTypeResolver了,
internal sealed class WebHostHttpControllerTypeResolver : DefaultHttpControllerTypeResolver
{
public override ICollection<Type> GetControllerTypes(IAssembliesResolver assembliesResolver)
{
HttpControllerTypeCacheSerializer serializer = new HttpControllerTypeCacheSerializer();
// First, try reading from the cache on disk
List<Type> matchingTypes = ReadTypesFromCache(TypeCacheName, IsControllerTypePredicate, serializer);
if (matchingTypes != null)
{
return matchingTypes;
}
// If reading from the cache failed, enumerate over every assembly looking for a matching type
matchingTypes = base.GetControllerTypes(assembliesResolver).ToList();
// Finally, save the cache back to disk
SaveTypesToCache(TypeCacheName, matchingTypes, serializer);
return matchingTypes;
}
}
现在我们有回到DefaultHttpControllerSelector的构造方法中来,这里的_controllerTypeCache已经明白是怎么一回事了,我们该来看看DefaultHttpControllerSelector的InitializeControllerInfoCache是怎么实现的。
private ConcurrentDictionary<string, HttpControllerDescriptor> InitializeControllerInfoCache()
{
var result = new ConcurrentDictionary<string, HttpControllerDescriptor>(StringComparer.OrdinalIgnoreCase);
var duplicateControllers = new HashSet<string>();
Dictionary<string, ILookup<string, Type>> controllerTypeGroups = _controllerTypeCache.Cache;
foreach (KeyValuePair<string, ILookup<string, Type>> controllerTypeGroup in controllerTypeGroups)
{
string controllerName = controllerTypeGroup.Key;
foreach (IGrouping<string, Type> controllerTypesGroupedByNs in controllerTypeGroup.Value)
{
foreach (Type controllerType in controllerTypesGroupedByNs)
{
if (result.Keys.Contains(controllerName))
{
duplicateControllers.Add(controllerName);
break;
}
else
{
result.TryAdd(controllerName, new HttpControllerDescriptor(_configuration, controllerName, controllerType));
}
}
}
}
foreach (string duplicateController in duplicateControllers)
{
HttpControllerDescriptor descriptor;
result.TryRemove(duplicateController, out descriptor);
}
return result;
}
这个方法就很简单了,我也不多说了,主要是创建HttpControllerDescriptor实例,在HttpControllerDescriptor构造函数中调有一个Initialize方法来做一些初始化的工作,而它也主要调用InvokeAttributesOnControllerType方法,具体实现:
private static void InvokeAttributesOnControllerType(HttpControllerDescriptor controllerDescriptor, Type type)
{
InvokeAttributesOnControllerType(controllerDescriptor, type.BaseType);
object[] attrs = type.GetCustomAttributes(inherit: false);
foreach (object attr in attrs)
{
var controllerConfig = attr as IControllerConfiguration;
if (controllerConfig != null)
{
var originalConfig = controllerDescriptor.Configuration;
var controllerSettings = new HttpControllerSettings(originalConfig);
controllerConfig.Initialize(controllerSettings, controllerDescriptor);
controllerDescriptor.Configuration = HttpConfiguration.ApplyControllerSettings(controllerSettings, originalConfig);
}
}
}
由于默认情况下我们没有IControllerConfiguration特性所以这里这个也就忽略吧。到这里DefaultHttpControllerSelector中SelectController的_controllerInfoCache.Value.TryGetValue(controllerName, out controllerDescriptor)也就很好明白了。
现在我们回到HttpControllerDispatcher中SendAsyncInternal方法来,这里有
IHttpController httpController = httpControllerDescriptor.CreateController(request);,我们知道httpControllerDescriptor是一个HttpControllerDescriptor实例,它的CreateController方法如下:
public class HttpControllerDescriptor
{
public virtual IHttpController CreateController(HttpRequestMessage request)
{
IHttpControllerActivator activator = Configuration.Services.GetHttpControllerActivator();
IHttpController instance = activator.Create(request, this, ControllerType);
return instance;
}
}
从DefaultServices中我们可以知道这里的activator 是DefaultHttpControllerActivator实例,这里的DefaultHttpControllerActivator.Create方法实现非常复杂,里面涉及到表达式树。
现在我们回到HttpControllerDispatcher的SendAsyncInternal方法中来,现在IHttpController实例我们已经创建好了,然后创建HttpControllerContext实例,
HttpControllerContext controllerContext = new HttpControllerContext(httpControllerDescriptor.Configuration, routeData, request);
controllerContext.Controller = httpController;
controllerContext.ControllerDescriptor = httpControllerDescriptor;
最后调用IHttpController的ExecuteAsync方法,到这里我们才真正进入到controller的方法调用中来
相关文章推荐
- Asp.net web Api源码分析-HttpRequestMessage的创建
- Asp.net web Api源码分析-HttpActionDescriptor的创建
- Asp.net web Api源码分析-HttpRequestMessage的创建
- Asp.net web Api源码分析-HttpActionDescriptor的创建
- Asp.net web Api源码分析-HttpControllerDispatcher
- Asp.net web Api源码分析-HttpParameterBinding
- Asp.net web Api源码分析-HttpResponseMessage
- asp.net mvc源码分析-Controllerl篇 如何创建Controller实例
- Asp.net web Api源码分析-HttpParameterBinding
- Asp.net web Api源码分析-HttpResponseMessage
- Asp.net web Api源码分析-HttpServer的创建
- 目标HttpController在ASP.NET Web API中是如何被激活的:目标HttpController的创建
- Asp.net web Api源码分析-HttpServer的创建
- asp.net mvc源码分析-Controllerl篇 如何创建Controller实例
- Asp.net web Api源码分析-如何获取IHttpHandler
- Asp.net web Api源码分析-ParameterBindingAttribute
- Asp.net web Api源码分析-如何获取IHttpHandler
- Asp.net web Api源码分析-Action的执行
- ASP.NET Web API的HttpController是如何被激活的?
- Asp.net web Api源码分析-Action的执行