白话ASP.NET MVC之三:Controller是如何解析出来的
??? 我们在上一篇文章中介绍Controller激活系统中所涉及到的一些类型,比如有关Controller类型的相关定义类型就包括了IController类型,IAsyncController类型,ControllerBase抽象类型和我们最终要使用的抽象类型Controller,这是ASP.NET MVC 框架中和Controller本身定义相关的类型。其他辅助类型,包括管理Controller的类型ControllerFactory,这个工厂负责Controller的生产和销毁。我们还涉及到另一个辅助类型,用于把系统默认定义的或者自定义的ControllerFactory注册到ASP.NET MVC框架中的类型ControllerBuilder。 1 [TypeForwardedFrom("System.Web.Routing,Version=3.5.0.0,Culture=Neutral,PublicKeyToken=31bf3856ad364e35")] 2 public class UrlRoutingModule : IHttpModule 3 { 4 private static readonly object _contextKey = new object(); 5 6 object _requestDataKey = 7 8 private RouteCollection _routeCollection; 9 10 public RouteCollection RouteCollection 11 { 12 get 13 { 14 if (this._routeCollection == null) 15 { 16 this._routeCollection = RouteTable.Routes; 17 } 18 return this._routeCollection; 19 } 20 set 21 22 value; 23 24 } 25 26 protected virtual void Dispose() 27 28 29 30 Init(HttpApplication application) 31 32 if (application.Context.Items[UrlRoutingModule._contextKey] != 33 34 return; 35 36 application.Context.Items[UrlRoutingModule._contextKey] = UrlRoutingModule._contextKey; 37 application.PostResolveRequestCache += new EventHandler(.OnApplicationPostResolveRequestCache); 38 39 40 void OnApplicationPostResolveRequestCache( sender,EventArgs e) 41 42 HttpContextBase context = new HttpContextWrapper(((HttpApplication)sender).Context); 43 .PostResolveRequestCache(context); 44 45 46 [Obsolete(This method is obsolete. Override the Init method to use the PostMapRequestHandler event.47 PostMapRequestHandler(HttpContextBase context) 48 49 50 51 PostResolveRequestCache(HttpContextBase context) 52 53 RouteData routeData = .RouteCollection.GetRouteData(context); 54 if (routeData == 55 56 57 58 IRouteHandler routeHandler = routeData.RouteHandler; 59 if (routeHandler == 60 61 throw new InvalidOperationException(string.Format(CultureInfo.CurrentCulture,SR.GetString(UrlRoutingModule_NoRouteHandler"),object[0])); 62 63 if (routeHandler is StopRoutingHandler) 64 65 66 67 RequestContext requestContext = RequestContext(context,routeData); 68 context.Request.RequestContext = requestContext; 69 IHttpHandler httpHandler = routeHandler.GetHttpHandler(requestContext); 70 if (httpHandler == 71 72 string.Format(CultureInfo.CurrentUICulture,1)">UrlRoutingModule_NoHttpHandler[] 73 74 routeHandler.GetType() 75 })); 76 77 if (!(httpHandler UrlAuthFailureHandler)) 78 79 context.RemapHandler(httpHandler); 80 81 82 if (FormsAuthenticationModule.FormsAuthRequired) 83 84 UrlAuthorizationModule.ReportUrlAuthorizationFailure(HttpContext.Current,1)">); 85 86 87 new HttpException(401,1)">Assess_Denied_Description3)); 88 89 90 IHttpModule.Dispose() 91 92 .Dispose(); 93 94 95 IHttpModule.Init(HttpApplication application) 96 97 .Init(application); 98 99 } ? 具体来说,该组件通过以RouteTable的静态属性Routes表示的路由表针对当前请求实施路由解析,如果有匹配,就会根据路由对象Route来生成RouteData路由数据对象,然后我们借助RouteData对象的RouteHandler属性获取想要的HttpHandler对象。在默认情况下这个RouteHandler属性所代表的对象是MvcRouteHandler。翠花,上代码: 1 /// <summary>Creates an object that implements the IHttpHandler interface and passes the request context to it.</summary> MvcRouteHandler : IRouteHandler IControllerFactory _controllerFactory; 6 Initializes a new instance of the <see cref="T:System.Web.Mvc.MvcRouteHandler" /> class. 7 MvcRouteHandler() 8 9 10 11 class using the specified factory controller object.12 <param name="controllerFactory">The controller factory.</param> 13 MvcRouteHandler(IControllerFactory controllerFactory) 14 15 this._controllerFactory = controllerFactory; 16 17 18 Returns the HTTP handler by using the specified HTTP context.19 <returns>The HTTP handler.</returns> 20 <param name="requestContext">The request context.21 virtual IHttpHandler GetHttpHandler(RequestContext requestContext) 22 23 requestContext.HttpContext.SetSessionStateBehavior(.GetSessionStateBehavior(requestContext)); 24 MvcHandler(requestContext); 25 26 27 Returns the session behavior.28 The session behavior.29 SessionStateBehavior GetSessionStateBehavior(RequestContext requestContext) string text = (string)requestContext.RouteData.Values[controller]; 33 string.IsNullOrWhiteSpace(text)) 34 35 InvalidOperationException(MvcResources.MvcRouteHandler_RouteValuesHasNoController); 36 37 IControllerFactory controllerFactory = this._controllerFactory ?? ControllerBuilder.Current.GetControllerFactory(); 38 controllerFactory.GetControllerSessionBehavior(requestContext,text); 39 40 41 Returns the HTTP handler by using the specified request context.42 43 IHttpHandler IRouteHandler.GetHttpHandler(RequestContext requestContext) 45 46 .GetHttpHandler(requestContext); 47 48 } ? 在该类型里面包含了一个IControllerFactory类型成员字段,这个接口类型是所有ControllerFactory都要必须实现的接口,否则就不叫Controller的工厂了。MvcRouteHandler类型有两个构造函数,无参的没的说,另一个需要传递一个IControllerFactory类型的参数,这个参数用于初始化MvcRouteHandler类型内部包含的类型为IControllerFactory的_controllerFactory字段。当我们构造MvcRouteHandler实例的时候,如果我们调用了无参的构造函数,它会在内部使用ControllerBuilder.Current.GetControllerFactory()方法来获取我们通过ControllerBuilder类型注册的IControllerFactory类型的实例,代码很明显: IControllerFactory controllerFactory = this._controllerFactory ?? ControllerBuilder.Current.GetControllerFactory();
? MvcRouteHandler实现了IRouteHandler接口,目的只有一个,提供后续的HttpHandler,IRouteHandler接口定义如下: interface IRouteHandler { IHttpHandler GetHttpHandler(RequestContext requestContext); } ?? MvcRouteHandler会给我们直接返回MvcHandler对象,这个对象用于处理请求,包括激活Controler对象,代码最有说服力,这份代码,上篇文章也贴过,现在也贴一下把,上代码: 1 MvcHandler : IHttpAsyncHandler,IHttpHandler,IRequiresSessionState 2 3 struct ProcessRequestState 4 5 internal IAsyncController AsyncController; 6 7 IControllerFactory Factory; 8 9 RequestContext RequestContext; 10 11 internal ReleaseController() 12 13 this.Factory.ReleaseController(.AsyncController); 14 15 16 17 object _processRequestTag = 18 19 string MvcVersion = MvcHandler.GetMvcVersionString(); 20 21 Contains the header name of the ASP.NET MVC version. 22 string MvcVersionHeaderName = X-AspNetMvc-Version 23 24 ControllerBuilder _controllerBuilder; 25 26 ControllerBuilder ControllerBuilder 27 28 29 30 this._controllerBuilder == 31 { 32 this._controllerBuilder = ControllerBuilder.Current; 33 } 34 ._controllerBuilder; 35 36 37 38 39 40 41 42 Gets or sets a value that indicates whether the MVC response header is disabled. 43 true if the MVC response header is disabled; otherwise,false. 44 bool DisableMvcResponseHeader 45 46 get 47 set 48 49 50 Gets a value that indicates whether another request can use the <see cref="T:System.Web.IHttpHandler" /> instance. 51 true if the instance is reusable; otherwise,1)"> 52 IsReusable 53 54 55 56 false 57 58 59 60 Gets the request context. 61 62 RequestContext RequestContext 63 64 65 66 67 68 69 70 IHttpHandler.IsReusable 71 72 73 74 .IsReusable; 75 76 77 78 <see cref="T:System.Web.Mvc.MvcHandler" /> 79 80 <exception cref="T:System.ArgumentNullException">The <paramref name="requestContext" /> parameter is null.</exception> 81 MvcHandler(RequestContext requestContext) 82 83 if (requestContext == 84 85 new ArgumentNullException(requestContext 86 87 this.RequestContext = 88 89 90 Adds the version header by using the specified HTTP context. 91 <param name="httpContext">The HTTP context. 92 AddVersionHeader(HttpContextBase httpContext) 93 94 if (!MvcHandler.DisableMvcResponseHeader) 95 96 httpContext.Response.AppendHeader(MvcHandler.MvcVersionHeaderName,MvcHandler.MvcVersion); 97 98 99 100 Called by ASP.NET to begin asynchronous request processing.101 The status of the asynchronous call.102 103 <param name="callback">The asynchronous callback method.104 <param name="state">The state of the asynchronous object.105 virtual IAsyncResult BeginProcessRequest(HttpContext httpContext,AsyncCallback callback,1)"> state) 106 107 HttpContextBase httpContext2 = HttpContextWrapper(httpContext); 108 .BeginProcessRequest(httpContext2,callback,state); 109 110 111 Called by ASP.NET to begin asynchronous request processing using the base HTTP context.112 113 114 115 116 virtual IAsyncResult BeginProcessRequest(HttpContextBase httpContext,1)">117 118 IController controller; 119 IControllerFactory factory; 120 this.ProcessRequestInit(httpContext,1)">out controller,1)">out factory); 121 IAsyncController asyncController = controller as IAsyncController; 122 if (asyncController != 123 124 BeginInvokeDelegate<MvcHandler.ProcessRequestState> beginDelegate = delegate(AsyncCallback asyncCallback,1)"> asyncState,MvcHandler.ProcessRequestState innerState) 125 126 IAsyncResult result; 127 try 128 { 129 result = innerState.AsyncController.BeginExecute(innerState.RequestContext,asyncCallback,asyncState); 130 } 131 catch 132 133 innerState.ReleaseController(); 134 throw135 136 result; 137 }; 138 EndInvokeVoidDelegate<MvcHandler.ProcessRequestState> endDelegate = delegate(IAsyncResult asyncResult,1)">139 140 141 142 innerState.AsyncController.EndExecute(asyncResult); 143 144 finally 145 146 147 148 149 MvcHandler.ProcessRequestState invokeState = MvcHandler.ProcessRequestState 150 151 AsyncController = asyncController,152 Factory = factory,1)">153 RequestContext = .RequestContext 154 155 SynchronizationContext synchronizationContext = SynchronizationContextUtil.GetSynchronizationContext(); 156 return AsyncResultWrapper.Begin<MvcHandler.ProcessRequestState>(callback,state,beginDelegate,endDelegate,invokeState,MvcHandler._processRequestTag,-1,synchronizationContext); 157 158 Action action = delegate 159 160 161 162 controller.Execute(.RequestContext); 163 164 165 166 factory.ReleaseController(controller); 167 168 }; 169 AsyncResultWrapper.BeginSynchronous(callback,action,MvcHandler._processRequestTag); 170 171 172 Called by ASP.NET when asynchronous request processing has ended.173 <param name="asyncResult">The asynchronous result.174 EndProcessRequest(IAsyncResult asyncResult) 175 176 AsyncResultWrapper.End(asyncResult,1)">177 178 179 GetMvcVersionString() 180 181 new AssemblyName(typeof(MvcHandler).Assembly.FullName).Version.ToString(2182 183 184 Processes the request by using the specified HTTP request context.185 186 ProcessRequest(HttpContext httpContext) 187 188 HttpContextBase httpContext2 = 189 .ProcessRequest(httpContext2); 190 191 192 Processes the request by using the specified base HTTP request context.193 194 ProcessRequest(HttpContextBase httpContext) 195 196 197 IControllerFactory controllerFactory; 198 controllerFactory); 199 200 201 controller.Execute(202 203 204 205 controllerFactory.ReleaseController(controller); 206 207 208 209 void ProcessRequestInit(HttpContextBase httpContext,1)">out IController controller,1)"> IControllerFactory factory) 210 211 HttpContext current = HttpContext.Current; 212 if (current != null && ValidationUtility.IsValidationEnabled(current) == true213 214 ValidationUtility.EnableDynamicValidation(current); 215 216 .AddVersionHeader(httpContext); 217 .RemoveOptionalRoutingParameters(); 218 string requiredString = this.RequestContext.RouteData.GetRequiredString(219 factory = .ControllerBuilder.GetControllerFactory(); 220 controller = factory.CreateController(.RequestContext,requiredString); 221 if (controller == 222 223 224 225 factory.GetType(),1)">226 requiredString 227 })); 228 229 230 231 RemoveOptionalRoutingParameters() 232 233 RouteValueDictionary values = .RequestContext.RouteData.Values; 234 values.RemoveFromDictionary((KeyValuePair<string,1)">object> entry) => entry.Value == UrlParameter.Optional); 235 236 237 Enables processing of HTTP Web requests by a custom HTTP handler that implements the interface.238 An <see cref="T:System.Web.HttpContext" /> object that provides references to the intrinsic server objects (for example,Request,Response,Session,and Server) that are used to service HTTP requests.239 IHttpHandler.ProcessRequest(HttpContext httpContext) 240 241 .ProcessRequest(httpContext); 242 243 244 245 246 <param name="context">247 <param name="cb">248 <param name="extraData">The data.249 IAsyncResult IHttpAsyncHandler.BeginProcessRequest(HttpContext context,AsyncCallback cb,1)"> extraData) 250 251 .BeginProcessRequest(context,cb,extraData); 252 253 254 255 <param name="result">256 IHttpAsyncHandler.EndProcessRequest(IAsyncResult result) 257 258 .EndProcessRequest(result); 259 260 }
1 2 3 4 5 6 7 10 this.ProcessRequestInit(httpContext,out controller,out factory); 11 IAsyncController asyncController = controller 12 14 BeginInvokeDelegate<MvcHandler.ProcessRequestState> beginDelegate = 17 18 19 result =20 21 24 26 28 EndInvokeVoidDelegate<MvcHandler.ProcessRequestState> endDelegate = 29 30 32 34 37 39 MvcHandler.ProcessRequestState invokeState = 40 41 AsyncController =42 Factory =43 RequestContext = 45 SynchronizationContext synchronizationContext =46 48 Action action = 50 51 52 controller.Execute(53 54 56 58 59 60 }
1 3 HttpContext current = 4 5 6 8 9 10 11 factory = 12 controller = factory.CreateController(this.RequestContext,1)">13 15 21 } ? ?? 这个方法主要是获取ControllerFactory实例,根据获得的ControllerFactory对象激活Controller对象,红色标注的代码就是核心关键点。说明一点,这个方法只是定义了激活Controller算法的骨架,具体的实现在DefaultControllerFactory类型中。代码很简单,我相信大家看的清楚。 1 Represents the controller factory that is registered by default. 2 DefaultControllerFactory : IControllerFactory 3 4 DefaultControllerActivator : IControllerActivator 5 6 private Func<IDependencyResolver> _resolverThunk; 7 8 public DefaultControllerActivator() : this( 9 10 11 12 DefaultControllerActivator(IDependencyResolver resolver) 13 14 if (resolver == 16 this._resolverThunk = (() => DependencyResolver.Current); 17 18 19 resolver); 20 21 22 IController Create(RequestContext requestContext,Type controllerType) 23 24 IController result; 25 26 27 result = (IController)(this._resolverThunk().GetService(controllerType) ?? Activator.CreateInstance(controllerType)); 28 29 catch (Exception innerException) 30 31 32 controllerType 34 }),innerException); 36 38 39 40 readonly ConcurrentDictionary<Type,SessionStateBehavior> _sessionStateCache = new ConcurrentDictionary<Type,SessionStateBehavior> 42 static ControllerTypeCache _staticControllerTypeCache = ControllerTypeCache(); 43 IBuildManager _buildManager; 45 46 private IResolver<IControllerActivator> _activatorResolver; 47 48 IControllerActivator _controllerActivator; 50 51 ControllerTypeCache _instanceControllerTypeCache; 53 54 IControllerActivator ControllerActivator 56 58 this._controllerActivator != 59 60 ._controllerActivator; 61 62 this._controllerActivator = ._activatorResolver.Current; 63 64 65 66 67 IBuildManager BuildManager 68 69 70 71 this._buildManager == 72 73 this._buildManager = BuildManagerWrapper(); 74 75 ._buildManager; 77 78 79 this._buildManager = 80 81 82 83 85 87 this._controllerBuilder ?? 89 90 91 92 94 95 ControllerTypeCache ControllerTypeCache 97 99 this._instanceControllerTypeCache ?? DefaultControllerFactory._staticControllerTypeCache; 100 101 102 103 this._instanceControllerTypeCache =104 105 106 107 <see cref="T:System.Web.Mvc.DefaultControllerFactory" />108 public DefaultControllerFactory() : null,1)">110 111 class using a controller activator.<param name="controllerActivator">An object that implements the controller activator interface.114 public DefaultControllerFactory(IControllerActivator controllerActivator) : this(controllerActivator,1)">115 116 117 118 internal DefaultControllerFactory(IControllerActivator controllerActivator,IResolver<IControllerActivator> activatorResolver,IDependencyResolver dependencyResolver) if (controllerActivator != 121 122 this._controllerActivator = controllerActivator; 123 124 125 IResolver<IControllerActivator> arg_44_1 = activatorResolver; 126 if (activatorResolver == 127 128 arg_44_1 = new SingleServiceResolver<IControllerActivator>(() => new DefaultControllerFactory.DefaultControllerActivator(dependencyResolver),DefaultControllerFactory constructor129 130 this._activatorResolver = arg_44_1; 131 132 133 static InvalidOperationException CreateAmbiguousControllerException(RouteBase route,1)">string controllerName,ICollection<Type> matchingTypes) 134 135 StringBuilder stringBuilder = StringBuilder(); 136 foreach (Type current in138 stringBuilder.AppendLine(); stringBuilder.Append(current.FullName); 140 141 Route route2 = route Route; 142 message; 143 if (route2 != 144 145 message = controllerName,1)"> route2.Url,1)">149 stringBuilder,1)"> Environment.NewLine 151 }); 152 153 else 155 message = 156 158 160 162 InvalidOperationException(message); 164 165 static InvalidOperationException CreateDirectRouteAmbiguousControllerException(ICollection<Type>167 StringBuilder stringBuilder = 168 169 171 172 173 string message = 174 stringBuilder,1)"> Environment.NewLine }); 178 179 180 181 Creates the specified controller by using the specified request context.182 The controller.183 The context of the HTTP request,which includes the HTTP context and route data.<param name="controllerName">The name of the controller.186 <exception cref="T:System.ArgumentException"><paramref name="controllerName" /> parameter is null or empty.187 virtual IController CreateController(RequestContext requestContext,1)"> controllerName) 188 191 192 193 string.IsNullOrEmpty(controllerName) && !requestContext.RouteData.HasDirectRouteMatch()) 194 195 new ArgumentException(MvcResources.Common_NullOrEmpty,1)">controllerName197 Type controllerType = .GetControllerType(requestContext,controllerName); .GetControllerInstance(requestContext,controllerType); 199 200 201 Retrieves the controller instance for the specified request context and controller type.202 The controller instance.203 204 <param name="controllerType">The type of the controller.205 <exception cref="T:System.Web.HttpException"> 206 /// <paramref name="controllerType" /> is null.207 <exception cref="T:System.ArgumentException"> 208 cannot be assigned.209 <exception cref="T:System.InvalidOperationException">An instance of cannot be created.210 IController GetControllerInstance(RequestContext requestContext,1)">211 if (controllerType == 214 404,MvcResources.DefaultControllerFactory_NoControllerFound,1)">216 requestContext.HttpContext.Request.Path 217 218 219 typeof(IController).IsAssignableFrom(controllerType)) 220 221 new ArgumentException(223 controllerType 224 }),1)">controllerType226 .ControllerActivator.Create(requestContext,1)">228 229 Returns the controller's session behavior.230 The controller's session behavior.231 232 233 SessionStateBehavior GetControllerSessionBehavior(RequestContext requestContext,1)">234 235 236 237 SessionStateBehavior.Default; 238 239 return DefaultControllerFactory._sessionStateCache.GetOrAdd(controllerType,1)">(Type type) 241 SessionStateAttribute sessionStateAttribute = type.GetCustomAttributes(typeof(SessionStateAttribute),1)">true).OfType<SessionStateAttribute>().FirstOrDefault<SessionStateAttribute>242 if (sessionStateAttribute == 243 244 245 246 sessionStateAttribute.Behavior; 247 248 249 250 Retrieves the controller type for the specified name and request context.251 The controller type.252 253 254 virtual Type GetControllerType(RequestContext requestContext,1)">255 256 258 260 string.IsNullOrEmpty(controllerName) && (requestContext.RouteData == null || !requestContext.RouteData.HasDirectRouteMatch())) 261 262 263 264 RouteData routeData = requestContext.RouteData; 265 if (routeData != null && routeData.HasDirectRouteMatch()) 266 267 DefaultControllerFactory.GetControllerTypeFromDirectRoute(routeData); 268 269 obj; 270 if (routeData.DataTokens.TryGetValue(Namespaces",1)"> obj)) 271 272 IEnumerable<string> enumerable = obj as IEnumerable<string>273 if (enumerable != null && enumerable.Any<()) 274 275 HashSet<string> namespaces = new HashSet<(enumerable,StringComparer.OrdinalIgnoreCase); 276 Type controllerTypeWithinNamespaces = .GetControllerTypeWithinNamespaces(routeData.Route,controllerName,namespaces); 277 if (controllerTypeWithinNamespaces != null || false.Equals(routeData.DataTokens[UseNamespaceFallback])) 278 279 controllerTypeWithinNamespaces; 280 281 282 283 this.ControllerBuilder.DefaultNamespaces.Count > 284 285 HashSet<string> namespaces2 = string>(.ControllerBuilder.DefaultNamespaces,1)">286 Type controllerTypeWithinNamespaces = 287 288 289 290 291 292 this.GetControllerTypeWithinNamespaces(routeData.Route,1)">293 294 295 static Type GetControllerTypeFromDirectRoute(RouteData routeData) 296 297 IEnumerable<RouteData> directRouteMatches = routeData.GetDirectRouteMatches(); 298 List<Type> list = new List<Type>299 foreach (RouteData current directRouteMatches) 300 301 302 303 Type targetControllerType = current.GetTargetControllerType(); 304 if (targetControllerType == 305 306 InvalidOperationException(MvcResources.DirectRoute_MissingControllerType); 307 308 list.Contains(targetControllerType)) 309 310 list.Add(targetControllerType); 311 312 313 314 if (list.Count == 315 316 317 318 319 320 return list[321 322 DefaultControllerFactory.CreateDirectRouteAmbiguousControllerException(list); 323 324 325 private Type GetControllerTypeWithinNamespaces(RouteBase route,HashSet< namespaces) 326 327 this.ControllerTypeCache.EnsureInitialized(.BuildManager); 328 ICollection<Type> controllerTypes = .ControllerTypeCache.GetControllerTypes(controllerName,1)">329 switch (controllerTypes.Count) 330 331 case : 332 333 334 return controllerTypes.First<Type>335 default336 DefaultControllerFactory.CreateAmbiguousControllerException(route,controllerTypes); 337 338 339 340 Releases the specified controller.341 <param name="controller">The controller to release.342 ReleaseController(IController controller) 343 344 IDisposable disposable = controller IDisposable; 345 if (disposable != 346 347 disposable.Dispose(); 348 349 350 351 internal IReadOnlyList<Type> GetControllerTypes() 352 353 354 .ControllerTypeCache.GetControllerTypes(); 355 356 357 This API supports the ASP.NET MVC infrastructure and is not intended to be used directly from your code. This method calls the <see cref="M:System.Web.Mvc.DefaultControllerFactory.GetControllerSessionBehavior(System.Web.Routing.RequestContext,System.Type)" /> method.358 359 360 The controller name.361 SessionStateBehavior IControllerFactory.GetControllerSessionBehavior(RequestContext requestContext,1)">362 363 364 365 366 367 .IsNullOrEmpty(controllerName)) 368 369 370 371 Type controllerType = 372 .GetControllerSessionBehavior(requestContext,1)">373 374 }
2 3 4 5 6 9 10 11 12 17 Type controllerType = this18 return 19 }
9 11 13 15 RouteData routeData =16 18 20 23 IEnumerable<26 HashSet<27 Type controllerTypeWithinNamespaces = 28 30 34 36 HashSet<37 Type controllerTypeWithinNamespaces = 40 42 43 44 } ??? 我们先根据RouteData路由数据来获取Controller的类型对象,如果RouteData不为空,并且在RouteData的Values属性中包含Key为“MS_DirectRouteMatches”的值,那我们就据此获取Controller的类型对象,如果没找到就返回Null值,如果有一个值,就会作为Controller的Type类型值返回,如果多于一个就会抛出异常。如果RouteData不包含Key为“MS_DirectRouteMatches”的值,我们就根据RouteData对象中DataTokens属性Key为“Namespaces”来获取Controller的Type对象,同理,如果没找到就返回null,找到一个就直接返回,如果多余一个的话就抛出异常。 protected string controllerName) ???????????? 其实这也是一个扩展点,但是我们今天不扩展这里,因为IOC框架和这里的关系不大,我们要扩展的是第二受保护的虚方法,方法签名如下: virtual IController GetControllerInstance(RequestContext requestContext,Type controllerType)
?????????? 这个方法是用于创建Controller实例的,这里正好可以使用IOC容器来管理Controller实例,当然在DefaultControllerFactory类型中还有其他的扩展点,大家可以自己去看,全部代码我以前也贴出来过。 1 UnityControllerFactory:DefaultControllerFactory <summary> /// IOC的容器对象 public IUnityContainer UnityContainer { get; ; } 8 9 通过构造函数初始化IOC的容器对象 10 11 <param name="unityContainer">传入的IOC容器对象 UnityControllerFactory(IUnityContainer unityContainer) if (unityContainer != this.UnityContainer = unityContainer; 20 容器对象不能为空!23 24 25 /// 26 27 <param name="requestContext"></param> 28 <param name="controllerType"></param> 29 <returns></returns> 30 override32 34 36 return (IController).UnityContainer.Resolve(controllerType); 38 }
Provides fine-grained control over how controllers are instantiated using dependency injection. IControllerActivator { When implemented in a class,creates a controller.</summary> The created controller.</returns> </param> IController Create(RequestContext requestContext,Type controllerType); } ?? 该接口中定义了Create方法实现针对目标Controller对象的创建,两个参数分别表示请求上下文和Controller的类型。我们在看看DefaultControllerFactory和ControllerActivator之间的关系吧,DefaultControllerFactory类型有三个构造函数,代码如下: 4 } 7 11 14 16 17 19 IResolver<IControllerActivator> arg_44_1 =22 arg_44_1 = new DefaultControllerFactory.DefaultControllerActivator(dependencyResolver),1)">24 25 }
1 NinjectControllerActivator : IControllerActivator 3 public IKernel Kernel { 4 5 NinjectControllerActivator() 7 this.Kernel = StandardKernel(); 11 .Kernel.TryGet(controllerType); 13 14 void Register<TFrom,TTo>() where TTo : TFrom 16 this.Kernel.Bind<TFrom>().To<TTo>18 } ???? 扩展写好了,还需要在Global.asax文件里面进行注册,否则不能使用。IOC相关的内容就不介绍了,大家可以自行研究。 1 3 5 8 18 19 IController result; 22 24 result = (IController)(26 30 controllerType }),1)">35 } ????????? 其实DefaultControllerActivator对象要像创建目标Controller对象,还依赖另外一个叫DependencyResolver的对象。所有的DenpendencyResolver类型均实现了IDenpendencyResolver接口,接口定义如下: Defines the methods that simplify service location and dependency resolution. IDependencyResolver 4 Resolves singly registered services that support arbitrary object creation. 5 The requested service or object.<param name="serviceType">The type of the requested service or object. GetService(Type serviceType); 9 Resolves multiply registered services.10 The requested services.The type of the requested services.12 IEnumerable<object> GetServices(Type serviceType); 13 } ???????? 系统中使用的DependencyResolver是通过DependencyResolver类型注册的。DependencyResolver类型有一个叫做Current的静态属性,该属性表示的是当前的、IDependencyResolver类型的对象。我们可以通过静态方法SetResolver来注册IDependencyResolver对象。需要说明一点,还有静态方法的DependencyResolver类型并没有实现IDependencyResolver接口,所以说该类型并不是真正的DependencyResolver类型,我们可以把它理解为一个Facade,它汇集了所要使用的对象和方法而已,使用更方便。 NinjectDependencyResolver : IDependencyResolver NinjectDependencyResolver() 10 14 GetService(Type serviceType) 17 .Kernel.TryGet(serviceType); 19 public IEnumerable< GetServices(Type serviceType) .Kernel.GetAll(serviceType); 24 }
(编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
- ASP.NET Core&EntityFramework核心:左(外)加入Linq
- asp.net-core – 无法从Client访问IdentityServer4 doc示例
- 如何阻止IIS 8停止空闲的ASP.NET应用程序?
- asp.net-mvc – ASP.NET MVC 1和2在Mono 2.4与Fluent NHibe
- 在netcore中实现字段和属性注入
- ASP.NET -- WebForm -- HttpRequest类的方法和属性
- asp.net – 在Publish上自动压缩html和css?
- asp.net-mvc – Asp.Net Mvc JQuery ajax输入参数为null
- .NET Core多平台开发体验[4]: Docker
- 破解SQL Prompt 3.9的几步操作
- asp.net-mvc – asp.net mvc嵌套视图模型表单sum
- asp.net – web.config urlmapping
- asp-classic – 经典ASP页面可以在Azure中运行吗
- .net core 使用Rotativa创建PDF文档
- Visual Studio 2017 ASP.NET Core开发
- 如何找到ASP.NET中的哪个对象无法序列化?
- asp.net-mvc – 如何为ASP.NET MVC区域捆绑资源?
- ASP.NET MVC 5无法呈现jQuery UI CSS包
- 如何模拟我的ASP.NET应用程序的HTTP 500错误?
- asp.net-mvc – 检查上传的文件是否是C#ASP.NET