zoukankan      html  css  js  c++  java
  • [源码学习]调试Razor从哪里开始

    使用ASP.NET MVC时,我们知道,要使用Views中的视图,需要在Action中写

    return View();

    这个方法返回的返回值是一个 ViewResult,进入这个类,继承了父类ViewResultBase后只写了MasterName属性和FindView方法。

    不过已经开始看到到ViewEngine的踪影了。

            protected override ViewEngineResult FindView(ControllerContext context) {
                ViewEngineResult result = ViewEngineCollection.FindView(context, ViewName, MasterName);
                ...;
            }
     

    跟进ViewEngineCollection.FindView去看看。

    来到了ViewEngineCollection类,这是一个实现了Collection<IViewEngine>的类。

            public virtual ViewEngineResult FindView(ControllerContext controllerContext, string viewName, string masterName) {
                if (controllerContext == null) {
                    throw new ArgumentNullException("controllerContext");
                }
                if (string.IsNullOrEmpty(viewName)) {
                    throw new ArgumentException(MvcResources.Common_NullOrEmpty, "viewName");
                }
    
                return Find(e => e.FindView(controllerContext, viewName, masterName, true),
                            e => e.FindView(controllerContext, viewName, masterName, false));
            }
     
    很简单的一个方法,跟进去
     
          private ViewEngineResult Find(Func<IViewEngine, ViewEngineResult> cacheLocator, Func<IViewEngine, ViewEngineResult> locator) {
                // First, look up using the cacheLocator and do not track the searched paths in non-matching view engines
                // Then, look up using the normal locator and track the searched paths so that an error view engine can be returned
                return Find(cacheLocator, trackSearchedPaths: false)
                    ?? Find(locator, trackSearchedPaths: true);
            }
    
            private ViewEngineResult Find(Func<IViewEngine, ViewEngineResult> lookup, bool trackSearchedPaths) {
                // Returns
                //    1st result
                // OR list of searched paths (if trackSearchedPaths == true)
                // OR null
                ViewEngineResult result;
    
                List<string> searched = null;
                if (trackSearchedPaths) {
                    searched = new List<string>();
                }
    
                foreach (IViewEngine engine in CombinedItems) {
                    if (engine != null) {
                        result = lookup(engine);
    
                        if (result.View != null) {
                            return result;
                        }
    
                        if (trackSearchedPaths) {
                            searched.AddRange(result.SearchedLocations);
                        }
                    }
                }
    
                if (trackSearchedPaths) {
                    // Remove duplicate search paths since multiple view engines could have potentially looked at the same path
                    return new ViewEngineResult(searched.Distinct().ToList());
                }
                else {
                    return null;
                }
            }
     

    乍一看,又是for又是if、else的有点不知所措,其实仔细一看结合上面的Find参数就能找到黄色加亮的几句代码关键代码。

    是遍历了注册ViewEngine集合,调用ViewEngine各自的FindView,谁能找到View,就用谁。

    那么遍历的ViewEngine集合怎么来的呢?要回到ViewResult的父类ViewResultBase中去看。

            public ViewEngineCollection ViewEngineCollection {
                get {
                    return _viewEngineCollection ?? ViewEngines.Engines;
                }
                set {
                    _viewEngineCollection = value;
                }
            }

    如果没有定义那么就调用ViewEngines.Engines,这是一个很简单的静态类属性

        public static class ViewEngines {
    
            private readonly static ViewEngineCollection _engines = new ViewEngineCollection {
                new WebFormViewEngine(),
                new RazorViewEngine(),
            };
    
            public static ViewEngineCollection Engines {
                get {
                    return _engines;
                }
            }
        }

    回到刚才的遍历,由于RazorViewEngine的构造函数中定义了以下格式,在Views文件夹中也创建了相应的文件,所以选择了RazorViewEngine。

     AreaViewLocationFormats = new[] {
                    "~/Areas/{2}/Views/{1}/{0}.cshtml",
                    "~/Areas/{2}/Views/{1}/{0}.vbhtml",
                    "~/Areas/{2}/Views/Shared/{0}.cshtml",
                    "~/Areas/{2}/Views/Shared/{0}.vbhtml"
                };
     
    好了,终于找到了Razor。
  • 相关阅读:
    python自动生成bean类
    CVPR2021 | SETR: 使用 Transformer 从序列到序列的角度重新思考语义分割
    经典论文系列 | 缩小Anchor-based和Anchor-free检测之间差距的方法:自适应训练样本选择
    单阶段实例分割综述
    CVPR2021提出的一些新数据集汇总
    使用 PyTorch Lightning 将深度学习管道速度提高 10 倍
    C#中使用ref和out传参的方法及区别
    读书笔记《重构 改善既有代码的设计》(第2版本)
    《大话设计模式》等读后感
    OOP、封装、继承、多态,真的懂了吗?
  • 原文地址:https://www.cnblogs.com/llcto/p/2531470.html
Copyright © 2011-2022 走看看