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

作者:   出处:互联网   2015-07-06 11:09:09   阅读:4

如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; 


 

第一步,动态编译:解析视图文件,生成代码,是的,生成代码,先。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);      } 


 

第二步就简单多了,就和任何静态类一样,用反射创建实例,然后复制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;  } 


 

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


 

public abstract class TemplateBase  {  public string Layout { get; set; }  public UrlHelper Url { get; set; }  public Func string  RenderBody { get; set; }  public string Path { get; internal 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 { get; set; }   } 
Copyright© 2006-2015 ComponentCN.com all rights reserved.重庆磐岩科技有限公司(控件中国网) 版权所有 渝ICP备12000264号 法律顾问:元炳律师事务所
客服软件
live chat