用Razor語法寫範本-RazorEngine組件介紹【转——非常好,可以用它来代替NVelocity】

RazorEngine

官網網址:http://razorengine.codeplex.com

在找到RazorEngine之前曾經想過其他的方案,如T4與V8 Engine載jquery.template,但T4如果要獨立於MSBuild或Visual Studio執行有點麻煩,而V8 Engine我又不想在Class Library專案中放一堆js檔,後來就想到Razor,因為Razor的相關處理都是寫在System.Web.Razor,雖然Namespace叫System.Web,但根本沒有載入任何的System.Web相關的組件(如圖一),所以我肯定它可以獨立在非Web環境於中使用,在研究如何運用的期間,就發現早在去年就有人寫好放在CodePlex上,我太落伍了。

用Razor語法寫範本-RazorEngine組件介紹【转——非常好,可以用它来代替NVelocity】

圖一 System.Web.Razor的參考,只有載入基本的三個組件

註:有興趣知道如何使用System.Web.Razor產生結果(基本上都是CodeDom),我所知道就有四套,小弟這一篇[ASP.NET MVC]Razor Views 預編譯(Pre-Compile)[1]-加快第一次執行回應速度介紹的二個Extension與本篇的RazorEngine與ASP.NET MVC 3使用的System.Web.WebPages.Razor,除了System.Web.WebPages.Razor外都是Open Source的可以下載Code來觀摩。

下面的範例,將展示如果只單獨使用System.Web.Razor.dll,如何產生結果(有點累,還是用別人的組件比較好)。

namespace RezorCodeDomSample

{

    internal class Program

    {

        private static void Main(string[] args)

        {

            //簡單的範本    

            string template = @"@{var name=""Would"";}

                                Hello @name!!";



            var input = new System.IO.StringReader(template);



            //產生Razor的TemplateEngine

            var host = new RazorEngineHost(new CSharpRazorCodeLanguage());

            host.DefaultBaseClass = "RezorCodeDomSample.MyTemplate";

            host.DefaultNamespace = "RezorCodeDomSample";

            host.DefaultClassName = "MyTemplateResult";

            var engine = new RazorTemplateEngine(host);



            //取得結果的CodeDom

            var code = engine.GenerateCode(input);

            var codeType = code.GeneratedCode.Namespaces[0].Types[0];

            var codeProvider = new CSharpCodeProvider();



            //將CodeDom輸出到檔案中

            //CodeGeneratorOptions options = new CodeGeneratorOptions();

            //options.BlankLinesBetweenMembers = true;

            //System.IO.StringWriter sw = new System.IO.StringWriter();

            //codeProvider.GenerateCodeFromCompileUnit(code.GeneratedCode, sw, options);

            //File.WriteAllText("c:\\text.cs", sw.ToString());



            //將CodeDom編譯

            var options = new CompilerParameters()

            {

                GenerateInMemory = true,

                GenerateExecutable = false,

            };

            options.ReferencedAssemblies.Add(typeof(Program).Assembly.Location);

            var asselby = codeProvider.CompileAssemblyFromDom(options, code.GeneratedCode);



            //執行Template

            var type = asselby.CompiledAssembly.GetType("RezorCodeDomSample.MyTemplateResult");

            var ins = Activator.CreateInstance(type) as MyTemplate;

            ins.Execute();

            Console.Write(ins.Reault);

        }

    }



    //如果沒有Base類會不好處理

    public class MyTemplate

    {

        private StringBuilder sb = new StringBuilder();



        public virtual void Execute()

        {

        }



        public void Write(object value)

        {

            sb.Append(value);

        }



        public void WriteLiteral(object value)

        {

            sb.Append(value);

        }



        public string Reault

        {

            get { return sb.ToString(); }

        }

    }

}

 

 

使用範例(部份直接使用官網的範例)

一般用法

string template = "Hello @Model.Name! Welcome to Razor!";

string result = Razor.Parse(template, new { Name = "World" }, "Sample");

 

最後一個參數Name是選項參數,但建議給值因為關係到快取,如果有給,下次使用相同名稱的範本會用快取的,而且關係到範本的Include,雖然RazorEngine不能用RanderAction或RanderPartial但有提供Include可以載入,也是使用此Name為關鍵字。

 

使用.cshtml檔案

只要是副檔名為.cshtml,就算不在ASP.NET MVC3專案中,編輯.cshtml的方式都相同(但缺web.config中的設定,所以有些功能出不來),當然範本檔副檔名不一定要為.cshtml,但有IDE支援總比沒有好。

只是寫法要變,因為ASP.NET MVC 3的BaseType是System.Web.Mvc.WebViewPage,而RazorEngine的BaseType是RazorEngine.Templating.TemplateBase,除了Model屬性外其他的Html、Url、Ajax等等屬性都不沒有,但是C#的語法都支援。

用Razor語法寫範本-RazorEngine組件介紹【转——非常好,可以用它来代替NVelocity】

string result = Razor.Parse(File.ReadAllText("test.cshtml"), new { IsVip = true, Name = "Wade" });

 

進階用法

Template的Include

RazorEngine雖然不支援RanderAction或RanderPartial,不過他有提供Include方法,載入已經Compile(或Parse)過的範本,以下是使用範例:

string template1 = "Hello @Model.Name";

string template2 = "This is my sample template, @Include(\"Template1\",Model)";

Razor.Compile(template1, "Template1");

string result = Razor.Parse(template2, new { Name = "Wade" });

內嵌方法

如果只有單一個範本會用到的方法可以使用內嵌方法,以下是使用範例:

string template = @"

@helper MyMethod(string name) {

  Hello @name

}



@MyMethod(Model.Name)! Welcome to Razor!";



string result = Razor.Parse(template, new { Name = "World" });

 

 

BaseType

每一個範本,最後都會使用System.Web.Razor.RazorTemplateEngine編譯成Class,而且繼承BaseType,所以BaseType決定了範本能使用的功能,如果還是不清楚以第一個範例為例:

@"@{var name=""Would"";}

  Hello @name!!";

 

這些內容經剖析後會變成這樣

//與第一個範例拿掉註解後所產生的test.cs檔案相同

namespace RezorCodeDomSample

{

    public class MyTemplateRsult : RezorCodeDomSample.MyTemplate

    {

        public MyTemplateRsult()

        {

        }



        public override void Execute()

        {

            var name = "Would";



            WriteLiteral("Hello ");





            Write(name);

            WriteLiteral("!!\r\n");

        }

    }

}

 

這樣有比較清楚BaseType的功用了嗎?

所以如果希望所有的範本都可以使用的功能,可以繼承RazorEngine.Templating.TemplateBase,將擴充功能寫在子類別,然後註冊子類別,以下是使用範例:

public abstract class MyCustomTemplateBase<T> : TemplateBase<T>

{

  public string ToUpperCase(string name)

  {

    return name.ToUpperCase();

  }

}



//註冊子類

Razor.SetTemplateBase(typeof(MyCustomTemplateBase<>));



string template = "My name in UPPER CASE is: @ToUpperCase(Model.Name)";

string result = Razor.Parse(template, new { Name = "Matt" });

 

 

載入組件與命名空間

RazorEngine註冊CodeDom所使用的組件是使用AppDomain.CurrentDomain.GetAssemblies()的方式,所以只要在專案中所參考的組件,範本中都可以使用,還有為了增加撰寫的便利性,可以增加命名空間,以下是使用範例:

 
Razor.DefaultTemplateService.Namespaces.Add("System.Xml");



string template = @"@{

     var xml = new XmlDocument();

     xml.LoadXml(Model);

     Write(xml.InnerXml);

}";

string result = Razor.Parse<string>(template, "<Test>test</Test>");

 

 

設定檔

跟ASP.NET MVC 3一樣,命名空間或BaseType等等都可以寫在設定檔中,詳情請參考官網

增加區段

<?xml version="1.0" encoding="UTF-8" ?>

<configuration>

    <configSections>

        <section name="razorEngine" type="RazorEngine.Configuration.RazorEngineConfigurationSection, RazorEngine" requirePermission="false" />

    </configSections>

</configuration>

 

增加設定

<razorEngine activator="RazorEngineSamples.Activators.MySampleActivator, RazorEngineSamples"

             factory="RazorEngine.Web.WebCompilerServiceFactory, RazorEngine.Web">

    <namespaces>

        <add namespace="System.Linq" />

    </namespaces>

    <templateServices default="myCustomTemplateService">

        <add name="myCustomTemplateService1" language="CSharp" />

        <add name="myCustomTemplateService2" templateBase="MyTemplateBase"/>

    </templateServices>

</razorEngine>

 

 

TemplateService可以讓某些範本使用不同的設定,以下是使用範例:

var service = Razor.Services["myCustomTemplateService"];

string result = service.Parse("Hello @Model.Name", new { Name = "World" });

 

 

原文地址:http://www.dotblogs.com.tw/wadehuang36/archive/2011/08/07/razor-template-engine.aspx

你可能感兴趣的:(velocity)