博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
ASP.NET MVC 源码分析(二) —— 从 IRouteBuilder认识路由构建
阅读量:6029 次
发布时间:2019-06-20

本文共 5884 字,大约阅读时间需要 19 分钟。

  我们来看IRouteBuilder的定义:

public interface IRouteBuilder    {        IRouter DefaultHandler { get; set; }        IServiceProvider ServiceProvider { get; }        IList
Routes { get; } IRouter Build(); }

一个默认的IRouter对象,一个Build方法,一个IRouter集合和一个获取服务对象IServiceProvider。

我们进一步看IRouteBuilder的实现RouterBuilder:

public class RouteBuilder : IRouteBuilder    {        public RouteBuilder()        {            Routes = new List
(); } public IRouter DefaultHandler { get; set; } public IServiceProvider ServiceProvider { get; set; } public IList
Routes { get; private set; } public IRouter Build() { var routeCollection = new RouteCollection(); foreach (var route in Routes) { routeCollection.Add(route); } return routeCollection; } }
View Code

主要的实现是Build方法,这个方法的实现也很简单,遍历Routes向一个实现了IRouter接口的RouteCollection对象添加IRouter,我们可以先看一下RouteCollection的实现:

public class RouteCollection : IRouteCollection    {        private readonly List
_routes = new List
(); private readonly List
_unnamedRoutes = new List
(); private readonly Dictionary
_namedRoutes = new Dictionary
(StringComparer.OrdinalIgnoreCase); private RouteOptions _options; public IRouter this[int index] { get { return _routes[index]; } } public int Count { get { return _routes.Count; } } 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) { for (var i = 0; i < Count; i++) { var route = this[i]; var oldRouteData = context.RouteData; var newRouteData = new RouteData(oldRouteData); newRouteData.Routers.Add(route); try { context.RouteData = newRouteData; await route.RouteAsync(context); if (context.IsHandled) { break; } } finally { if (!context.IsHandled) { context.RouteData = oldRouteData; } } } } public virtual VirtualPathData GetVirtualPath(VirtualPathContext context) { EnsureOptions(context.Context); // If we're using Best-Effort link generation then it means that we'll first look for a route where // the route values are validated (context.IsBound == true). If we can't find a match like that, then // we'll return the path from the first route to return one. var useBestEffort = _options.UseBestEffortLinkGeneration; if (!string.IsNullOrEmpty(context.RouteName)) { var isValidated = false; VirtualPathData bestPathData = null; INamedRouter matchedNamedRoute; if (_namedRoutes.TryGetValue(context.RouteName, out matchedNamedRoute)) { bestPathData = matchedNamedRoute.GetVirtualPath(context); isValidated = context.IsBound; } // If we get here and context.IsBound == true, then we know we have a match, we want to keep // iterating to see if we have multiple matches. foreach (var unnamedRoute in _unnamedRoutes) { // reset because we're sharing the context context.IsBound = false; var pathData = unnamedRoute.GetVirtualPath(context); if (pathData == null) { continue; } if (bestPathData != null) { // There was already a previous route which matched the name. throw new InvalidOperationException( Resources.FormatNamedRoutes_AmbiguousRoutesFound(context.RouteName)); } else if (context.IsBound) { // This is the first 'validated' match that we've found. bestPathData = pathData; isValidated = true; } else { Debug.Assert(bestPathData == null); // This is the first 'unvalidated' match that we've found. bestPathData = pathData; isValidated = false; } } if (isValidated || useBestEffort) { context.IsBound = isValidated; if (bestPathData != null) { bestPathData = new VirtualPathData( bestPathData.Router, NormalizeVirtualPath(bestPathData.VirtualPath), bestPathData.DataTokens); } return bestPathData; } else { return null; } } else { VirtualPathData bestPathData = null; for (var i = 0; i < Count; i++) { var route = this[i]; var pathData = route.GetVirtualPath(context); if (pathData == null) { continue; } if (context.IsBound) { // This route has validated route values, short circuit. return new VirtualPathData( pathData.Router, NormalizeVirtualPath(pathData.VirtualPath), pathData.DataTokens); } else if (bestPathData == null) { // The values aren't validated, but this is the best we've seen so far bestPathData = pathData; } } if (useBestEffort) { return new VirtualPathData( bestPathData.Router, NormalizeVirtualPath(bestPathData.VirtualPath), bestPathData.DataTokens); } else { return null; } } } private PathString NormalizeVirtualPath(PathString path) { var url = path.Value; if (!string.IsNullOrEmpty(url) && _options.LowercaseUrls) { var indexOfSeparator = url.IndexOfAny(new char[] { '?', '#' }); // No query string, lowercase the url if (indexOfSeparator == -1) { url = url.ToLowerInvariant(); } else { var lowercaseUrl = url.Substring(0, indexOfSeparator).ToLowerInvariant(); var queryString = url.Substring(indexOfSeparator); // queryString will contain the delimiter ? or # as the first character, so it's safe to append. url = lowercaseUrl + queryString; } return new PathString(url); } return path; } private void EnsureOptions(HttpContext context) { if (_options == null) { _options = context.RequestServices.GetRequiredService
>().Options; } } }

 乍一看这个类的功能还是比较庞大的,我们主要关注他对IRouter接口签名的实现:

Task RouteAsync(RouteContext context):

通过代码我们可以看到,这个方法主要对RouteCollection本身持有的Route 规则循环添加到路由上下文RouteContext.RouteData中。

VirtualPathData GetVirtualPath(VirtualPathContext context):

 

 

 

 

转载于:https://www.cnblogs.com/LiJianBlog/p/4557033.html

你可能感兴趣的文章
lnmp实例
查看>>
Android开发环境搭建(WINDOWS VERSION)
查看>>
kvm虚拟机的克隆和分区扩容
查看>>
代码中如何应对缓存服务器宕机的情况
查看>>
Intro to CSS 3D transforms
查看>>
《Java技术》第三次作业
查看>>
CYQ.Data 数据层框架 CYQ.Data 数据框架 使用篇四 MAction 增删改
查看>>
[sqlite] 判断表、视图是否存在及常用C#操作语句
查看>>
c++中,bool与int 的区别
查看>>
cout输出控制——位数和精度控制
查看>>
Parse 构建移动APP后台服务(一)
查看>>
ZT 过你想要的生活:需要追问自己的50个问题
查看>>
使用OpenSSL生成非对称密钥
查看>>
0.11.1版本docker安装与使用
查看>>
脖子和腰围的关系
查看>>
转一个权限设计
查看>>
【R】R语言使用命令行参数 - [编程技巧(Program Skill)]
查看>>
经典算法题每日演练——第二题 五家共井
查看>>
存储过程中拼接的变量和点的问题
查看>>
ASP.NET那点不为人知的事(一)
查看>>