あなたをオープンソースに連れて行きます-ASP.NET_MVC(五)


本は前述の通り、CreateViewメソッドを追跡し続け、抽象的なメソッドであることを発見しました.BuildManagerView EngineはVirtualPathProviderView Engineを継承していることを発見しましたが、CreateViewメソッドを書き換えていません.慌てないでください.私たちは模索を続け、RazorView EngineとWebFormViewEngine(彼にかかわらず)がBuildManagerView Engineを継承していることを発見しました.ここではRazorViewのCreateViewメソッド書き換え(コードセグメント1)のみを見る.
        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].
未完待续..