龙盟编程博客 | 无障碍搜索 | 云盘搜索神器
快速搜索
主页 > web编程 > asp.net编程 >

学习ASP.NET MVC设计模式(5):ViewEngine 深入解析与应用实例(2)

时间:2009-12-21 11:47来源:未知 作者:admin 点击:
分享到:
四.开发自定义ViewEngine 下面通过示例演示如何开发自己的ViewEngine.其中要用到StringTemplate这个模板引擎, 在老赵的的MVC视频教程中也使用的此引擎演示ViewE

四.开发自定义ViewEngine

下面通过示例演示如何开发自己的ViewEngine.其中要用到StringTemplate这个模板引擎, 在老赵的的MVC视频教程中也使用的此引擎演示ViewEngine. StringTemplate负责翻译一个模板页上面的占位符(aspx页面中的内嵌代码), 输出HTML.目前在StringTemplate的官方网站上已经提供了针对Asp.Net Mvc的ViewEngine.但是官方的ViewEngine模板没有使用VirtualPathProviderViewEngine基类.下面我将提供一种不能说更好但至少是另一种实现的StringTemplateViewEngine.其中需要使用StringTemplate的模版功能.

1. 实现IView接口

要开发一个自己的ViewEngine, 首先要创建实现了IView接口的类, 在此我们创建了名为StringTemplateView的类

public class StringTemplateView : IView
    {
        #region 属性 Properties
        /// <summary>
        /// StringTemplate 对象, 在构造函数中创建
        /// </summary>
        private StringTemplate StringTemplate 
        { 
            get; set; 
        }
        #endregion

        #region 构造函数 Constructed Function 
        private StringTemplateView()
        {
            //不用于使用不带参数的构造函数
            this.StringTemplate = new StringTemplate();
        }

        public StringTemplateView(StringTemplate template)
        {
            //null check
            if (template == null) throw new ArgumentNullException("template");

            //set template
            this.StringTemplate = template;
        }
        #endregion

        #region IView 成员

        void IView.Render(ViewContext viewContext, System.IO.TextWriter writer)
        {
            foreach(var item in viewContext.ViewData)
            {
                this.StringTemplate.SetAttribute(item.Key.ToString(), item.Value.ToString());
            }

            //为StringTemplate设置HttpContext
            this.StringTemplate.SetAttribute("context", viewContext.HttpContext);

            //输出模板
            NoIndentWriter noIndentWriter = new NoIndentWriter(writer);
            this.StringTemplate.Write(noIndentWriter);

        }

        #endregion
    }

StringTemplateView是在StringTemplate视图引擎中View角色的抽象, 所以功能是实现呈现页面的Render方法. StringTemplate的核心功能就是一套自己定义的模板输出引擎, 所以在构造StringTemplateView对象是必须传入一个StringTemplate实例,在Render时只是调用StringTemplate对象的模板输出方法.

2. 实现IViewEngine接口

有了IView对象. 接下来就要实现最核心的IViewEngine接口. 在具体的StringTemplateViewEngine类中, 要返回一个带有StringTemplateView对象的ViewEngineResult.

在我的实现方法中,使用了ASP.NET MVC已经提供的VirtualPathProviderViewEngine类作为我们的基类. VirtualPathProviderViewEngine类实现了IViewEngine接口的方法, 提供了在程序中寻找View物理文件路径的机制, 搜索时要使用在派生类中赋值的搜索路径.

下面是我们的StringTemplateViewEngine类实现:

    public class StringTemplateViewEngine : VirtualPathProviderViewEngine
    {
        private string _AppPath = string.Empty;

        #region 属性 Properties
        public static FileSystemTemplateLoader Loader { get; private set; }
        public static StringTemplateGroup Group { get; private set; }
        #endregion

        public StringTemplateViewEngine(string appPath)
        {
            _AppPath = appPath;
            Loader = new FileSystemTemplateLoader(appPath);
            Group = new StringTemplateGroup("views", Loader);

            MasterLocationFormats = new[] {
                "/Views/{1}/{0}.st",
                "/Views//Shared/{0}.st" 
            };

            ViewLocationFormats = MasterLocationFormats;

            PartialViewLocationFormats = MasterLocationFormats;
        }

        protected override IView CreatePartialView(ControllerContext controllerContext, string partialPath)
        {
            return this.CreateView(controllerContext, partialPath, String.Empty);
        }

        protected override IView CreateView(ControllerContext controllerContext, string viewPath, string masterPath)
        {            

            StringTemplate stringTemplate = Group.GetInstanceOf(viewPath.Replace(".st", ""));
            StringTemplateView result = new StringTemplateView(stringTemplate);
            return result;
        }
    }

注意首先在我们的StringTemplateViewEngine中,提供了搜索模板文件的路径,即先从View/{controller}中搜索,再从View/Share中搜索. 这样VirtualPathProviderViewEngine基类的方法就可以找到我们.st模板文件的具体路径, 然后使用StringTemplateViewEngine中提供的创建StringTemplateView的方法, 根据具体路径创建StringTemplateView对象.

在一些开源的ViewEngine中,尤其是MvcContrib项目中的ViewEngine都将创建View对象的功能放在一个ViewFactory类中, 个人认为这个更好的设计, 但是由于我们的StringTemplateViewEngine要继承VirtualPathProviderViewEngine, 所以没办法拆分创建View的方法.

至此我们已经完成了StringTemplateViewEngine的全部工作.


精彩图集

赞助商链接