Razor视图引擎学习

RazorView:

  RazorView和WebFormView都是继承自:BuildManageCompiledView。RazorView和WebFormView都有其各自对应的一个引擎:RazorViewEngine和WebFormViewEngine,今天咱们不讲WebFormView,主讲RazorView,我们来看看RazorView类型。在Razor引擎下,通过这一类型来表示View。

 1 public class RazorView : BuildManagerCompiledView
 2 {
 3     // Methods
 4     public RazorView(ControllerContext controllerContext, string viewPath, string layoutPath, bool runViewStartPages, IEnumerable<string> viewStartFileExtensions);
 5     public RazorView(ControllerContext controllerContext, string viewPath, string layoutPath, bool runViewStartPages, IEnumerable<string> viewStartFileExtensions, IViewPageActivator viewPageActivator);
 6     protected override void RenderView(ViewContext viewContext, TextWriter writer, object instance);
 7 
 8     // Properties
 9     internal DisplayModeProvider DisplayModeProvider { get; set; }
10     public string LayoutPath { get; private set; }
11     public bool RunViewStartPages { get; private set; }
12     internal StartPageLookupDelegate StartPageLookup { get; set; }
13     public IEnumerable<string> ViewStartFileExtensions { get; private set; }
14     internal IVirtualPathFactory VirtualPathFactory { get; set; }
15 }

RenderView方法重写了基类BuildManagerCompiledView的方法。 属性LayoutPath表示布局文件的虚拟路径,而RunViewStartPages则表示是否运行ViewSatrt视图

,ViewStartFileExtensions属性则表示的是ViewStart文件的后缀。例如:“cshtml”、"vbhtml"。我们再来看看其内部的一个很重要的方法:RenderView.

 1   protected override void RenderView(ViewContext viewContext, TextWriter writer, object instance)
 2     {
 3         if (writer == null)
 4         {
 5             throw new ArgumentNullException("writer");
 6         }
 7         WebViewPage page = instance as WebViewPage;
 8         if (page == null)
 9         {
10             throw new InvalidOperationException(string.Format(CultureInfo.CurrentCulture, MvcResources.CshtmlView_WrongViewBase, new object[] { base.ViewPath }));
11         }
12         page.OverridenLayoutPath = this.LayoutPath;
13         page.VirtualPath = base.ViewPath;
14         page.ViewContext = viewContext;
15         page.ViewData = viewContext.ViewData;
16         page.InitHelpers();
17         if (this.VirtualPathFactory != null)
18         {
19             page.VirtualPathFactory = this.VirtualPathFactory;
20         }
21         if (this.DisplayModeProvider != null)
22         {
23             page.DisplayModeProvider = this.DisplayModeProvider;
24         }
25         WebPageRenderingBase startPage = null;
26         if (this.RunViewStartPages)
27         {
28             startPage = this.StartPageLookup(page, RazorViewEngine.ViewStartFileName, this.ViewStartFileExtensions);
29         }
30         HttpContextBase httpContext = viewContext.HttpContext;
31         WebPageRenderingBase base4 = null;
32         object model = null;
33         page.ExecutePageHierarchy(new WebPageContext(httpContext, base4, model), writer, startPage);
34     }

在此方法中,首先是将传过来的object对象转换为一个WebViewPage对象,接着设置WebViewPage对象的page的布局文件路径,视图文件路径,以及ViewContext和ViewData属性。接着执行初始化,对WebViewPage内部的一些属性进行设置,接着判断执行ViewStart页面的情况,得到表示开启页面的WebPageRenderingBase对象。最后执行page对象的ExecutePageHierarchy方法, 运行执行管道的页层次结构。

来瞧瞧其基类:BuilderManagerCompiledView

 1 public abstract class BuildManagerCompiledView : IView
 2 {
     // Methods11     internal BuildManagerCompiledView(ControllerContext controllerContext, string viewPath, IViewPageActivator viewPageActivator, IDependencyResolver dependencyResolver);
12     public void Render(ViewContext viewContext, TextWriter writer);
13     protected abstract void RenderView(ViewContext viewContext, TextWriter writer, object instance);
14 
15     // Properties
16     internal IBuildManager BuildManager { get; set; }
17     public string ViewPath { get; protected set; }
18 }

BuilderManagerCompiledView提供了一个RenderView的抽象方法供子类重写,上面我们已经讲过RenderView方法,可以参考。其中有一个Render方法,我们来看看:

 1 public void Render(ViewContext viewContext, TextWriter writer)
 2 {
 3     if (viewContext == null)
 4     {
 5         throw new ArgumentNullException("viewContext");
 6     }
 7     object instance = null;
 8     Type compiledType = this.BuildManager.GetCompiledType(this.ViewPath);
 9     if (compiledType != null)
10     {
11         instance = this.ViewPageActivator.Create(this._controllerContext, compiledType);
12     }
13     if (instance == null)
14     {
15         throw new InvalidOperationException(string.Format(CultureInfo.CurrentCulture, MvcResources.CshtmlView_ViewCouldNotBeCreated, new object[] { this.ViewPath }));
16     }
17     this.RenderView(viewContext, writer, instance);
18 }

该方法中,首先是根据虚拟路径获得所在View的类型,然在根据类型和控制器上下文创建对象,这个方法最终还是调用了RenderView方法,将instance对象作为参数带入方法中.

可能你对BuildManagerCompiledView构造函数也感兴趣,特别是IViewPageActivator和IDependencyResolver。

1 internal BuildManagerCompiledView(ControllerContext controllerContext, string viewPath, IViewPageActivator viewPageActivator, IDependencyResolver dependencyResolver)
2 {
3     this._controllerContext = controllerContext;
4     this.ViewPath = viewPath;
5     this.ViewPageActivator = viewPageActivator ?? new BuildManagerViewEngine.DefaultViewPageActivator(dependencyResolver);
6 }

看到构造函数结尾对当前ViewPageActivator属性进行赋值的时候,给了一个默认值。看到了吧,当为null的时候,赋了一个DefaultViewPageActivator对象,此时构造函数中传入的参数是dependencyResolver对象。

Razor视图引擎:

 1 public class RazorViewEngine : BuildManagerViewEngine
 2 {
 3     // Fields
 4     internal static readonly string ViewStartFileName;
 5 
 6     // Methods
 7     static RazorViewEngine();
 8     public RazorViewEngine();
 9     public RazorViewEngine(IViewPageActivator viewPageActivator);
10     protected override IView CreatePartialView(ControllerContext controllerContext, string partialPath);
11     protected override IView CreateView(ControllerContext controllerContext, string viewPath, string masterPath);
12 }

RazorViewEngine继承自BuildManagerViewEngine,内部通过控制器上下文,重写了基类的CreatePartialView创建分布视图方法和CreateView创建视图方法。构造函数设置了视图的搜寻顺序,如果没有提供,则按照这个顺序进行搜寻。

原文地址:https://www.cnblogs.com/yangda/p/2994865.html