あなたをオープンソースに連れて行きます-ASP.NET_MVC(五)
本は前述の通り、CreateViewメソッドを追跡し続け、抽象的なメソッドであることを発見しました.BuildManagerView EngineはVirtualPathProviderView Engineを継承していることを発見しましたが、CreateViewメソッドを書き換えていません.慌てないでください.私たちは模索を続け、RazorView EngineとWebFormViewEngine(彼にかかわらず)がBuildManagerView Engineを継承していることを発見しました.ここではRazorViewのCreateViewメソッド書き換え(コードセグメント1)のみを見る.
コードセグメント1
コードセグメント1は、IViewオブジェクトを取得し、さらに「ソースを読む-ASP.NET_MVC(4)」コードセグメント10に対してViewEngineResultを取得し、「ソースを読む-ASP.NET_MVC(4)」コードセグメント2の文「result=FindView(context);View=result.View;これにより、Viewオブジェクトが得られ、Viewが呼び出されます.Render(viewContext,writer)メソッド、その中のwriterは何ですか?「TextWriter writer=context.HttpContext.Response.Output;」という文を見つけました.おおらかですか.私たちが久しぶりに考えたResponseがついに現れ、それがあれば、HTML応答をブラウザにレンダリングして送り返すことができ、これで、ブラウザからHTTP要求を出して、サーバーにHTML応答を送り返して、完全な回路を構成します.私は頼りにして、疲れました!
コードセグメント2を見てみましょう.これは、ブラウザにHTMLページをレンダリングする方法が1つしかないIViewインタフェースの定義です.
protected override IViewCreateView(ControllerContext controllerContext, string viewPath, stringmasterPath)
{
var view = newRazorView(controllerContext, viewPath,
layoutPath: masterPath, runViewStartPages: true,viewStartFileExtensions: FileExtensions, viewPageActivator: ViewPageActivator)
{
DisplayModeProvider =DisplayModeProvider
};
return view;
}
コードセグメント1
コードセグメント1は、IViewオブジェクトを取得し、さらに「ソースを読む-ASP.NET_MVC(4)」コードセグメント10に対してViewEngineResultを取得し、「ソースを読む-ASP.NET_MVC(4)」コードセグメント2の文「result=FindView(context);View=result.View;これにより、Viewオブジェクトが得られ、Viewが呼び出されます.Render(viewContext,writer)メソッド、その中のwriterは何ですか?「TextWriter writer=context.HttpContext.Response.Output;」という文を見つけました.おおらかですか.私たちが久しぶりに考えたResponseがついに現れ、それがあれば、HTML応答をブラウザにレンダリングして送り返すことができ、これで、ブラウザからHTTP要求を出して、サーバーにHTML応答を送り返して、完全な回路を構成します.私は頼りにして、疲れました!
コードセグメント2を見てみましょう.これは、ブラウザにHTMLページをレンダリングする方法が1つしかないIViewインタフェースの定義です.
<pre name="code" class="csharp"> public interface IView
{
void Render(ViewContext viewContext, TextWriterwriter);
}
代码段 2
只有一个类实现了IView接口,这个类就是BuildManagerCompiledView,我们看Render方法的具体实现,见代码段3。
public virtual void Render(ViewContextviewContext, TextWriter writer) { if (viewContext == null) { throw newArgumentNullException("viewContext"); } object instance = null; Type type =BuildManager.GetCompiledType(ViewPath); if (type != null) { instance =ViewPageActivator.Create(_controllerContext, type); } if (instance == null) { throw newInvalidOperationException( String.Format( CultureInfo.CurrentCulture, MvcResources.CshtmlView_ViewCouldNotBeCreated, ViewPath)); } RenderView(viewContext, writer,instance); }
コードセグメント3
コードセグメント3には、次の2つの点に注意する必要があります.
①【instance= ViewPageActivator.Create(_controllerContext, type);】
②【RenderView(viewContext,writer, instance);】
ここで、①は実体化ビュークラス、②はレンダリングビューである.主線を際立たせるために、まず②を分析します.RenderViewは抽象的な方法であることがわかりました.経験に基づいてBuildManagerCompilledViewクラスにはRenderViewメソッドを書き換えたサブクラスがあるはずです.ソースコードの中で探してみると、WebFormViewとRazorViewの2つのサブクラスがあることがわかりました.この2つのクラスを見て嬉しいでしょう.ほほほ!ここではまずRazorViewのRenderViewメソッド書き換えのみを解析し,コードセグメント4を参照する.
protected override voidRenderView(ViewContext viewContext, TextWriter writer, object instance) { if (writer == null) { throw newArgumentNullException("writer"); } WebViewPage webViewPage = instanceas WebViewPage; if (webViewPage == null) { throw newInvalidOperationException( String.Format( CultureInfo.CurrentCulture, MvcResources.CshtmlView_WrongViewBase, ViewPath)); } // An overriden master layout mighthave been specified when the ViewActionResult got returned. // We need to hold on to it so thatwe can set it on the inner page once it has executed. webViewPage.OverridenLayoutPath =LayoutPath; webViewPage.VirtualPath = ViewPath; webViewPage.ViewContext =viewContext; webViewPage.ViewData =viewContext.ViewData; webViewPage.InitHelpers(); if (VirtualPathFactory != null) { webViewPage.VirtualPathFactory= VirtualPathFactory; } if (DisplayModeProvider != null) { webViewPage.DisplayModeProvider= DisplayModeProvider; } WebPageRenderingBase startPage =null; if (RunViewStartPages) { startPage =StartPageLookup(webViewPage, RazorViewEngine.ViewStartFileName, ViewStartFileExtensions); } webViewPage.ExecutePageHierarchy(new WebPageContext(context:viewContext.HttpContext, page: null, model: null), writer, startPage); }
コードセグメント4
コードセグメント4で文【webViewPage.ExecutePageHierarchy(new WebPageContext(context:viewContext.HttpContext,page:null,model:null),writer,startPage)】,この文は、レンダリングを実行するコア文です.WebViewPageへのアクセスを追跡し続けます.ExecutePageHierarchy、コードセグメント5を参照してください.
// This method is only used byWebPageBase to allow passing in the view context and writer. public voidExecutePageHierarchy(WebPageContext pageContext, TextWriter writer,WebPageRenderingBase startPage) { PushContext(pageContext, writer); if (startPage != null) { if (startPage != this) { var startPageContext =WebPageContext.CreateNestedPageContext<object>(parentContext:pageContext, pageData: null, model: null, isLayoutPage: false); startPageContext.Page =startPage; startPage.PageContext = startPageContext; } startPage.ExecutePageHierarchy(); } else { ExecutePageHierarchy(); } PopContext(); }
コードセグメント5
コードセグメント5でExecutePageHierarchyメソッドを見つけ、その定義に入ります.コードセグメント6を参照してください.
[SuppressMessage("Microsoft.Design","CA1031:DoNotCatchGeneralExceptionTypes", Justification = "Wereally don't care if SourceHeader fails, and we don't want it to fail any realrequests ever")] public override voidExecutePageHierarchy() { // Unlike InitPages, for a WebPagethere is no hierarchy - it is always // the last file to execute in thechain. There can still be layout pages // and partial pages, but they arenever part of the hierarchy. // (add server header for falcondebugging) // call to MapPath() is expensive.If we are not emiting source files to header, // don't bother to populate theSourceFiles collection. This saves perf significantly. if(WebPageHttpHandler.ShouldGenerateSourceHeader(Context)) { try { string vp = VirtualPath; if (vp != null) { string path =Context.Request.MapPath(vp); if (!path.IsEmpty()) { PageContext.SourceFiles.Add(path); } } } catch { // we really don't care ifthis ever fails, so we swallow all exceptions } } TemplateStack.Push(Context, this); try { // Execute thedeveloper-written code of the WebPage Execute(); } finally { TemplateStack.Pop(Context); } }
コードセグメント6
コードセグメント6で文Execute()メソッドを見つけます.このメソッドの上に「//Execute thedeveloper-written code of the WebPage」という注釈があります.「開発者が作成したページコードを実行する」という意味です.分かりましたか?この文の機能は、あなたが書いたビューコードを実行することです.cshtmlファイル.では、疑問を提起する人がいるに違いありません.cshtmlファイルはどのように実行しますか?htmlスクリプトではありませんか?いいですね.cshtmlファイルは確かにhtmlスクリプトであり、直接実行できないため、ここで懸念を残している[1].
未完待续..