优化ETL过滤模块
大石头 authored at 2017-08-29 17:11:46
4.99 KiB
X
using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Web.Mvc;
using System.Web.WebPages;

namespace NewLife.Cube.Precompiled
{
    /// <summary>预编译视图</summary>
    public class PrecompiledMvcView : IView
    {
        private static Lazy<Action<WebViewPage, String>> _overriddenLayoutSetter = new Lazy<Action<WebViewPage, String>>(() => CreateOverriddenLayoutSetterDelegate());
        private readonly Type _type;
        private readonly String _virtualPath;
        private readonly String _masterPath;
        private readonly IViewPageActivator _viewPageActivator;

        /// <summary>是否运行视图开始页ViewStart</summary>
        public Boolean RunViewStartPages { get; private set; }

        /// <summary>视图开始页扩展</summary>
        public IEnumerable<String> ViewStartFileExtensions { get; private set; }

        /// <summary>虚拟路径</summary>
        public String VirtualPath { get { return _virtualPath; } }

        ///// <summary>实例化预编译视图</summary>
        ///// <param name="virtualPath"></param>
        ///// <param name="type"></param>
        ///// <param name="runViewStartPages"></param>
        ///// <param name="fileExtension"></param>
        //public PrecompiledMvcView(String virtualPath, Type type, Boolean runViewStartPages, IEnumerable<String> fileExtension) : this(virtualPath, null, type, runViewStartPages, fileExtension) { }

        ///// <summary>实例化预编译视图</summary>
        ///// <param name="virtualPath"></param>
        ///// <param name="masterPath"></param>
        ///// <param name="type"></param>
        ///// <param name="runViewStartPages"></param>
        ///// <param name="fileExtension"></param>
        //public PrecompiledMvcView(String virtualPath, String masterPath, Type type, Boolean runViewStartPages, IEnumerable<String> fileExtension) : this(virtualPath, masterPath, type, runViewStartPages, fileExtension, null) { }

        /// <summary>实例化预编译视图</summary>
        /// <param name="virtualPath"></param>
        /// <param name="masterPath"></param>
        /// <param name="type"></param>
        /// <param name="runViewStartPages"></param>
        /// <param name="fileExtension"></param>
        /// <param name="viewPageActivator"></param>
        public PrecompiledMvcView(String virtualPath, String masterPath, Type type, Boolean runViewStartPages, IEnumerable<String> fileExtension, IViewPageActivator viewPageActivator)
        {
            _type = type;
            _virtualPath = virtualPath;
            _masterPath = masterPath;
            RunViewStartPages = runViewStartPages;
            ViewStartFileExtensions = fileExtension;
            //_viewPageActivator = (viewPageActivator ?? (DependencyResolver.Current.GetService<IViewPageActivator>() ?? DefaultViewPageActivator.Current));
            _viewPageActivator = viewPageActivator;
        }

        /// <summary>生成视图内容</summary>
        /// <param name="viewContext"></param>
        /// <param name="writer"></param>
        public void Render(ViewContext viewContext, TextWriter writer)
        {
            var webViewPage = _viewPageActivator.Create(viewContext.Controller.ControllerContext, _type) as WebViewPage;
            if (webViewPage == null) throw new InvalidOperationException("无效视图类型");

            if (!String.IsNullOrEmpty(_masterPath))
            {
                _overriddenLayoutSetter.Value(webViewPage, _masterPath);
            }
            webViewPage.VirtualPath = _virtualPath;
            webViewPage.ViewContext = viewContext;
            webViewPage.ViewData = viewContext.ViewData;
            webViewPage.InitHelpers();

            WebPageRenderingBase startPage = null;
            if (RunViewStartPages) startPage = StartPage.GetStartPage(webViewPage, "_ViewStart", ViewStartFileExtensions);

            var pageContext = new WebPageContext(viewContext.HttpContext, webViewPage, null);
            webViewPage.ExecutePageHierarchy(pageContext, writer, startPage);
        }

        private static Action<WebViewPage, String> CreateOverriddenLayoutSetterDelegate()
        {
            var property = typeof(WebViewPage).GetProperty("OverridenLayoutPath", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
            if (property == null)
                throw new NotSupportedException("The WebViewPage internal property \"OverridenLayoutPath\" does not exist, probably due to an unsupported run-time version.");

            var setMethod = property.GetSetMethod(true);
            if (setMethod == null)
                throw new NotSupportedException("The WebViewPage internal property \"OverridenLayoutPath\" exists but is missing a set method, probably due to an unsupported run-time version.");

            return (Action<WebViewPage, String>)Delegate.CreateDelegate(typeof(Action<WebViewPage, String>), setMethod, true);
        }
    }
}