导航

09-010 Routing 之 RouteCollection

Posted on 2015-04-09 11:21  DotNet1010  阅读(196)  评论(0)    收藏  举报

看一下继承关系:

public class RouteCollection : IRouteCollection{}
public interface IRouteCollection : IRouter
    {
        void Add(IRouter router);
    }
    public interface IRouter
    {

	// 这里最终的目的是执行Controller 中的Action 方法 返回 输出结果
        Task RouteAsync(RouteContext context);

	// 返回生成的URL 
        string GetVirtualPath(VirtualPathContext context);
    }

 RouteCollection 是一个IRouter 的集合。

结合上一节的TemplateRoute

   public class TemplateRoute : INamedRouter{}
   public interface INamedRouter : IRouter
    {
        string Name { get; }
    }

 可以这么理解:RouteCollection 就是一个 TemplateRoute 的集合。

TemplateRoute 利用 RouteTemplate 和其它的条件 如 请求路径 和 VirtualPathContext  可以路由 可以生成URL。

路由的目的是找到具体的 Controller 和 Action 并执行。

生成URL的目的是 将特定的方法 生成URL 来继续请求。

核心方法有三个:1 Add 添加路由 分为 有名字的 和 无名字的。

 public void Add([NotNull] IRouter router)
        {
            var namedRouter = router as INamedRouter;
            if (namedRouter != null)
            {
                if (!string.IsNullOrEmpty(namedRouter.Name))
                {
                    _namedRoutes.Add(namedRouter.Name, namedRouter);
                }
            }
            else
            {
                _unnamedRoutes.Add(router);
            }

            _routes.Add(router);
        }

其它两个方法代码:

        public async virtual Task RouteAsync(RouteContext context)
        {
			/*
			  参数 RouteContext 怎么来的?
			   新创建一个  然后把 RouteCollection 添加进去 

			   var context = new RouteContext(httpContext);
               context.RouteData.Routers.Add(_router);

	       */

			EnsureLogger(context.HttpContext);
            using (_logger.BeginScope("RouteCollection.RouteAsync"))
            {
                for (var i = 0; i < Count; i++)
                {
                    var route = this[i];

					// old 包含所有的 TemplateRoute 
                    var oldRouteData = context.RouteData;

                    var newRouteData = new RouteData(oldRouteData);
					// 取出一个 TemplateRoute 
                    newRouteData.Routers.Add(route);

                    try
                    {
                        context.RouteData = newRouteData;

						//这时候 只有一个 TemplateRoute 
                        await route.RouteAsync(context);

                        if (context.IsHandled)
                        {
                            break;
                        }
                    }
                    finally
                    {
                        if (!context.IsHandled)
                        {
                            context.RouteData = oldRouteData;
                        }
                    }
                }

                if (_logger.IsEnabled(LogLevel.Verbose))
                {
                    _logger.WriteValues(new RouteCollectionRouteAsyncValues()
                    {
                        Handled = context.IsHandled,
                        Routes = _routes
                    });
                }
            }
        }

        public virtual string GetVirtualPath(VirtualPathContext context)
        {
            if (!string.IsNullOrEmpty(context.RouteName))
            {
				#region ----context.RouteName 按照已经命名的路由来生成 URL-------
				INamedRouter matchedNamedRoute;
                _namedRoutes.TryGetValue(context.RouteName, out matchedNamedRoute);

                var virtualPath = matchedNamedRoute != null ? matchedNamedRoute.GetVirtualPath(context) : null;
                foreach (var unnamedRoute in _unnamedRoutes)
                {
                    var tempVirtualPath = unnamedRoute.GetVirtualPath(context);
                    if (tempVirtualPath != null)
                    {
                        if (virtualPath != null)
                        {
							// 能匹配多个的报错
                            // There was already a previous route which matched the name.
                            throw new InvalidOperationException(
                                        Resources.FormatNamedRoutes_AmbiguousRoutesFound(context.RouteName));
                        }

                        virtualPath = tempVirtualPath;
                    }
                }

                return virtualPath;

				#endregion
			}
            else
            {
                for (var i = 0; i < Count; i++)
                {
                    var route = this[i];

                    var path = route.GetVirtualPath(context);
				   // 找到就返回
                    if (path != null)
                    {
                        return path;
                    }
                }
            }

            return null;
        }