【搬运外国同行文章】在非网页程序里使用razor模板引擎

【前言】近日研究代码生成,急需一个模板引擎,找到了一篇外国同行的文章,里面有如何在其他环境里面使用razor而且详细说明了原理,非常好,本人虽然英语战力<=5,但是也勉强看得懂,ok,原文地址如下:

Hosting the Razor Engine for Templating in Non-Web Applications


下面是本人的渣翻,如有错漏,请指正,谢谢。


如何在非网页程序里使用razor模板引擎?



  微软最近推出了razor模板引擎技术,虽然该技术与asp.net mvc 预览版捆绑在一起,但是它可以应用于非asp.net程序里面。 Razor是asp.net webform外的另一种模板技术,它可以代替目前广泛应用在webform和mvc上面的aspx模板技术。

【我就不逐句逐句翻译了,如何使用的翻译如下:】

假如你还没有下载这个项目的话,请返回原网址下载,或者点击这里下载:



开始


下面看一个基本的例子:
@inherits RazorHosting.RazorTemplateBase
@using System.Reflection
Hello @Context.FirstName! Your entry was entered on: @Context.Entered

@{
    // Code block: Update the host Windows Form passed in through the context
    Context.WinForm.Text = "Hello World from Razor at " + DateTime.Now.ToString();
}

AppDomain Id:
    @AppDomain.CurrentDomain.FriendlyName
            
Assembly:
    @Assembly.GetExecutingAssembly().FullName

Code based output: 
@{
    // Write output with Response object from code
    string output = string.Empty;
    for (int i = 0; i < 10; i++)
    {
        output += i.ToString() + " ";
    }
    Response.Write(output);
}

@inherits RazorHosting.RazorTemplateBase
备注:上面 的 inheribts将默认的模板类型改写成为 RazorTemplateBase,它并非必须的,但是它最大的好处在于,能够让 vs 提供这个模板类型的智能提示,何乐而不为?

上面是模板的内容,下面将介绍如何解析这个模板:
var engine = new RazorEngine<RazorTemplateBase>();

// we can pass any object as context - here create a custom context
var context = new CustomContext()
{
    WinForm = this,
    FirstName = "Rick",
    Entered = DateTime.Now.AddDays(-10)
};

string output = engine.RenderTemplate(this.txtSource.Text
                                      new string[] { "System.Windows.Forms.dll" },
                                      context);

if (output == null)
    this.txtResult.Text = "*** ERROR:\r\n" + engine.ErrorMessage;
else
    this.txtResult.Text = output;

这是最简单最快捷的方式,其中 CustomContext是作者(译者注:作者为 Rick Strahl)添加的一个上下文变量,用来传递到模板里面,在模板里面可以这样调用context的参数:
@Context.FirstName

值得提醒的是,并非所有对象都可以放进context里面,只有可序列化的对象才可以(假如包含有方法的对象,那么就不行了),否则会报错。

假如你不想将字符串传进来而直接用文件流来解析模板,那么可以这样用:

using (reader = new StreamReader("templates\\simple.csHtml", true))
{
    result = host.RenderTemplate(reader,  new string[] { "System.Windows.Forms.dll" }, 
                                 this.CustomContext);
}



上面解析模板的api都是RenderTemplate,这个是封装好的高级用法,假如您希望更加精确控制模板的分析行为,那么可以使用较底层的api,例如:

// we can pass any object as context - here create a custom context
var context = new CustomContext()
{
    WinForm = this,
    FirstName = "Rick",
    Entered = DateTime.Now.AddDays(-10)
};

var engine = new RazorEngine<RazorTemplateBase>();
string assId = null;

using (StringReader reader = new StringReader(this.txtSource.Text))
{
    assId = engine.ParseAndCompileTemplate(new string[] { "System.Windows.Forms.dll" }, reader);
}

string output = engine.RenderTemplateFromAssembly(assId, context);

if (output == null)
    this.txtResult.Text = "*** ERROR:\r\n" + engine.ErrorMessage;
else
    this.txtResult.Text = output;


注意:翻译到这里我就明白如何用这个东西了,假如你要调用自己的dll,譬如:Mytools.Common类库,那么就必须在解析模板的时候声明该dll,譬如:

    result = host.RenderTemplate(reader,  new string[] { "System.Windows.Forms.dll","Mytools.Common.dll" }, 
                                 this.CustomContext);

接下来的都是一些高级用法,各位有兴趣可以去原网址查阅。

备注:如何在vs里面获得代码提示功能?任意类库的提示。



这里以vs2010为例,其中:
这位兄弟帮了大忙。

首先,在项目下面添加一个web.config

里面内容如下:

<?xml version="1.0" encoding="utf-8"?>
<!--
  有关如何配置 ASP.NET 应用程序的详细信息,请访问
  http://go.microsoft.com/fwlink/?

LinkId=169433
  -->
<configuration>
  <configSections>

  </configSections>

  <connectionStrings>

  </connectionStrings>


  <appSettings>
    <add key="webpages:Version" value="2.0.0.0" />
    <add key="webpages:Enabled" value="false" />
    <add key="PreserveLoginUrl" value="true" />
    <add key="ClientValidationEnabled" value="true" />
    <add key="UnobtrusiveJavaScriptEnabled" value="true" />
  </appSettings>
  <system.web>
    <compilation debug="true">


      <assemblies>
        <add assembly="System.Web.Mvc, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
        <add assembly="System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
        <add assembly="System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />

      </assemblies>

      <!--
      <buildProviders>
    
        <add extension=".cshtml" 

type="Microsoft.WebPages.Compilation.InlinePageBuildProvider" />
       
      
      </buildProviders>
      -->


    </compilation>

    <pages>
      <namespaces>
        <add namespace="System.Web.Helpers" />
        <add namespace="System.Web.Mvc" />
        <add namespace="System.Web.Mvc.Ajax" />
        <add namespace="System.Web.Mvc.Html" />
        <add namespace="System.Web.Optimization" />
        <add namespace="System.Web.Routing" />
        <add namespace="System.Web.WebPages" />
        <add namespace="Easis.Common"/>
      </namespaces>
    </pages>
  </system.web>


  <system.webServer>

    <validation validateIntegratedModeConfiguration="false" />
    <modules runAllManagedModulesForAllRequests="true" />
    
    <handlers>
      <remove name="ExtensionlessUrlHandler-ISAPI-4.0_32bit" />
      <remove name="ExtensionlessUrlHandler-ISAPI-4.0_64bit" />
      <remove name="ExtensionlessUrlHandler-Integrated-4.0" />
      <add name="ExtensionlessUrlHandler-ISAPI-4.0_32bit" path="*." verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" modules="IsapiModule"

scriptProcessor="%windir%\Microsoft.NET\Framework\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness32" responseBufferLimit="0" />
      <add name="ExtensionlessUrlHandler-ISAPI-4.0_64bit" path="*." verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework64\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness64"

responseBufferLimit="0" />
      <add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
    </handlers>
  </system.webServer>
  <runtime>
    <assemblyBinding  xmlns="urn:schemas-microsoft-com:asm.v1">
      <dependentAssembly>
        <assemblyIdentity name="System.Web.Helpers"   publicKeyToken="31bf3856ad364e35" />
        <bindingRedirect oldVersion="1.0.0.0-2.0.0.0" newVersion="2.0.0.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35"/>
        <bindingRedirect oldVersion="1.0.0.0-4.0.0.0" newVersion="4.0.0.0" />
      </dependentAssembly>


      <dependentAssembly>
        <assemblyIdentity name="System.Web.WebPages" publicKeyToken="31bf3856ad364e35" />
        <bindingRedirect oldVersion="1.0.0.0-2.0.0.0" newVersion="2.0.0.0" />
      </dependentAssembly>
    </assemblyBinding>


  </runtime>

</configuration>

有了这个东西,以后在这个项目下面新建的任何cshtml文档都会有智能代码提示功能,但是对于第三方类库是没有提示的,如何解决?

请看:
    <compilation debug="true">


      <assemblies>
        <add assembly="System.Web.Mvc, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
        <add assembly="System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
        <add assembly="System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
        <add assembly="RazorHosting, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"/>
        <add assembly="Easis.Common,Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"/>
        <add assembly="Easis.Security, Version=1.0.0.0, Culture=neutral,PublicKeyToken=null"/>
      </assemblies>

在assemblies标签下面添加第三方类库,然后将第三方的dll都放到bin目录。。注意:没有bin目录的要新建一个,并且不能放在bin/debug或者bin/release下面,因为web config导入去的路径就是bin,你可以在 项目的生成里面设置输出路径为:
bin/
ok,做完这些你应该可以看到完美的代码提示功能了,

请注意,使用这个razorHosting的时候要请顺便将dll导进去,否则会报错。


下面再分享一个小工具,这个小工具的作用是分析dll文件,获得具体的引用信息,免得大家不知道version,publicktoken之类的信息 无法添加到web config里面。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值