逃脱Asp.Net MVC框架枷锁 使用Razor视图引擎

开发 架构 后端
如Razor引擎浅析所述,Razor的两大主要功能,模板文件和动态编译器。我们能不能单纯就要而且只要这俩主要特性? 其它那些智能查找视图文件等,虽不能说是垃圾,也是束缚手脚的条条框框,我完全可以自己做,失去的是一条绳索,获得是整个世界。

此文应该算Razor引擎浅析的续篇,或者说浅析是此文的前传。

为什么要这么做?

1. Asp.Net MVC 其实也不是太好

2. 我有自己的敏捷Web框架, 仍然想用Razor引擎

3. 动态编译很有意思,这也是将来的一个趋势,如果有人有兴趣,我倒是很想写写这方面的内容.

可是也有这些想法的人并不多,找来找去,这方面的资料和论述极其之少。与其临渊羡鱼,不如退而结网。自己动手,丰衣足食。

如Razor引擎浅析所述,Razor的两大主要功能,模板文件和动态编译器。我们能不能单纯就要而且只要这俩主要特性? 其它那些智能查找视图文件等,虽不能说是垃圾,也是束缚手脚的条条框框,我完全可以自己做,失去的是一条绳索,获得是整个世界。

保持模板功能,特别是设计时智能语法支持,很简单,创建项目时选择MVC项目,然后把其它MVC相关的引用删掉只剩下Razor就好了。

编译? 你根本就找不到这一段代码,被淹没在大量的辅助代码中。幸好,我这里已经找到了,简化修改之后,就剩下了了几行,你就可以直接使用在甚至不必是Web项目中。

首先, 用到的Razor域名空间。

using System.Web.Razor;  
using System.Web.Razor.Generator;  
using System.Web.Razor.Parser; 
  • 1.
  • 2.
  • 3.

第一步,动态编译:解析视图文件,生成代码,是的,生成代码,先。Razor的语法可以说是私有语法,需要先生成标准代码,然后才编译,生成我们熟悉的C#类Type。需要注意的是,我下面代码用的模板基类是我自己的TeamplateBase,后面会给出简单实现,当然,好处就是灵活性。你也可以直接用Asp.Net MVC的System.Web.Mvc.WebViewPage, 不过我没有试过,也许会有其他问题,不能保证。

public static Type Compile<T>(string template_path)  
      {  
          //准备临时类名,读取模板文件和Razor代码生成器  
          var class_name = "c" + Guid.NewGuid().ToString("N");  
          var base_type = typeof(TemplateBase<>).MakeGenericType(typeof(T));  
          var template = File.ReadAllText(template_path);  
   
          var host = new RazorEngineHost(new CSharpRazorCodeLanguage(), () => new HtmlMarkupParser())  
                         {  
   
                             DefaultBaseClass = base_type.FullName,  
                             DefaultClassName = class_name,  
                             DefaultNamespace = "YourNameSpace.dynamic",  
                             GeneratedClassContext =  
                                 new GeneratedClassContext("Execute""Write""WriteLiteral""WriteTo",  
                                                           "WriteLiteralTo",  
                                                           "YourNameSpace.TemplateBase")  
   
                         };  
          host.NamespaceImports.Add("System");  
          host.NamespaceImports.Add("YourNameSpaces");  
             
          //生成代码  
          CodeCompileUnit code;  
          using (var reader = new StringReader(template)) {  
              var generatedCode = new RazorTemplateEngine(host).GenerateCode(reader);  
              code = generatedCode.GeneratedCode;  
          }  
          //准备编译参数  
          var @params = new CompilerParameters  
          {  
              IncludeDebugInformation = false,  
              TempFiles = new TempFileCollection(AppDomain.CurrentDomain.DynamicDirectory),  
              CompilerOptions = "/target:library /optimize",  
              GenerateInMemory = false 
          };  
   
          var assemblies = AppDomain.CurrentDomain  
             .GetAssemblies()  
             .Where(a => !a.IsDynamic)  
             .Select(a => a.Location)  
             .ToArray();  
          @params.ReferencedAssemblies.AddRange(assemblies);  
   
          //编译  
          var provider = new CSharpCodeProvider();  
          var compiled = provider.CompileAssemblyFromDom(@params, code);  
   
          if (compiled.Errors.Count > 0) {  
              var compileErrors = string.Join("\r\n", compiled.Errors.Cast<object>().Select(o => o.ToString()));  
              throw new ApplicationException("Failed to compile Razor:" + compileErrors);  
          }  
   
          //编译成功后, 返回编译后的动态Type  
          return compiled.CompiledAssembly.GetType("Skight.Arch.Presentation.Web.Core.ViewEngins.Razor.dynamic." + class_name);  
   
   
      } 
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.
  • 49.
  • 50.
  • 51.
  • 52.
  • 53.
  • 54.
  • 55.
  • 56.
  • 57.
  • 58.

第二步就简单多了,就和任何静态类一样,用反射创建实例,然后复制Model对象执行模板,最后输出结果是,就自动吧Model类的数据嵌入了。

public static string Render<T>(T model,string template_path)  
      {  
          var type = Compile<T>(template_path);  
          //创建视图实例  
          var instance = (TemplateBase<T>)Activator.CreateInstance(type);  
   
          //执行模板(把数据嵌入文件)  
          instance.Model = model;  
          instance.Execute();  
          //输出最终结果  
          var result = instance.Result;  
   
          return result;  
      } 
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.

最后,看看视图模板类,一个基类和一个泛型基类,后者用于前类型Model

public abstract class TemplateBase  
    {  
        public string Layout { getset; }  
        public UrlHelper Url { getset; }  
        public Func<string> RenderBody { getset; }  
        public string Path { getinternal set; }  
        public string Result { get { return Writer.ToString(); } }  
   
        protected TemplateBase()  
        {  
        }  
   
        public TextWriter Writer  
        {  
            get 
            {  
                if(writer==null)  
                {writer = new StringWriter();  
                }  
                return writer;  
            }  
            set {  
                writer = value;  
            }  
        }  
   
        private TextWriter writer;  
   
        public void Clear() {  
           Writer.Flush();  
        }  
   
        public virtual void Execute() { }  
   
        public void Write(object @object) {  
            if (@object == null) {  
                return;  
            }  
            Writer.Write(@object);  
        }  
   
        public void WriteLiteral(string @string) {  
            if (@string == null) {  
                return;  
            }  
            Writer.Write(@string);  
        }  
   
        public static void WriteLiteralTo(TextWriter writer, string literal) {  
            if (literal == null) {  
                return;  
            }  
            writer.Write(literal);  
        }  
   
        public static void WriteTo(TextWriter writer, object obj) {  
            if (obj == null) {  
                return;  
            }  
            writer.Write(obj);  
        }  
    }  
    public abstract class TemplateBase<T> :TemplateBase  
    {  
        public T Model { getset; }              
    } 
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.
  • 49.
  • 50.
  • 51.
  • 52.
  • 53.
  • 54.
  • 55.
  • 56.
  • 57.
  • 58.
  • 59.
  • 60.
  • 61.
  • 62.
  • 63.
  • 64.
  • 65.
  • 66.

原文链接:http://www.cnblogs.com/Wonner/archive/2012/03/12/2391212.html

责任编辑:林师授 来源: 博客园
相关推荐

2021-06-22 16:59:56

微软.NETC# 软件开发

2011-01-19 11:17:36

2009-07-24 13:20:44

MVC框架ASP.NET

2012-05-09 13:29:42

ASP.NET

2009-07-22 10:09:59

ASP.NET MVC

2009-07-22 13:24:24

ASP.NET MVC

2009-07-20 10:53:59

ASP.NET MVC

2010-12-07 09:38:15

ASP.NET MVC

2009-07-22 10:34:37

ActionInvokASP.NET MVC

2009-07-22 13:08:55

拯救UpdatePanASP.NET MVC

2009-07-23 15:44:39

ASP.NET MVC

2010-06-23 15:44:03

ASP.NET MVC

2009-07-28 13:06:45

ASP.NET MVC

2014-06-30 09:22:38

ASP.NETBootstrap

2009-03-13 10:58:48

ASP.NetMVC框架编程

2009-07-20 12:59:53

ASP.NET MVCASP.NET框架的功

2009-07-31 12:43:59

ASP.NET MVC

2009-06-01 10:23:31

asp.net mvcasp.net mvc.net mvc框架

2009-07-20 15:51:40

FubuMVC核心框架ASP.NET MVC

2009-07-24 10:55:00

asp.net mvc
点赞
收藏

51CTO技术栈公众号