Microsoft Roslyn是微軟.NET「編譯器即服務(Compiler as a Service)」的主要產品,它提供了開放的編譯器API,併爲源代碼產生、分析和重構提供了新一代的語言對象模型。Anders Hejlsberg在BUILD 2013大會上提到,C# 6.0的編譯器將使用Roslyn實現,這一實現會包含在Visual Studio 2013以後的產品中。根據Anders的描述,C# 6.0的編譯器將採用C#開發,從而告別現有的本機代碼(native code)的實現方式,「雖然是採用C#來實現C#編譯器,但我想性能至少不會比原來的實現方式差。」node
有關Roslyn的內容,能夠參考如下連接:正則表達式
讓咱們先睹爲快,瞭解一下Roslyn的一個具體應用:提取C#和VB.NET代碼中的字符串常量。ide
先看下面的一段代碼:函數
using System; using System.Collections; using System.Linq; using System.Text; namespace HelloWorld { class Program { static void Main(string[] args) { // Output a "greeting" string Console.WriteLine("Hello, World!"); // Output another "say hello" string Console.WriteLine("Hi, nice to meet you!"); } } }
很明顯這段代碼中有四個字符串:greeting、Hello, World!、say hello和Hi, nice to meet you!,或許咱們能夠經過正則表達式來提取這些字符串,但請注意:這些字符串中有兩個是在註釋語句中出現的,而不是咱們所須要的字符串常量。咱們只須要獲得其中真正用於可執行代碼的Hello, World!和Hi, nice to meet you!,這若是經過正則表達式來區分仍是有必定難度的,並且對於字符串中的轉義字符等特殊字符的判斷和提取,正則表達式也略顯麻煩。性能
如今,讓咱們用Roslyn來完成這一工做。首先,打開Visual Studio 2012/2013,新建一個控制檯程序(Console Application),.NET Framework的版本選用4.5或者4.5.1。而後,在新建的控制檯程序項目上單擊右鍵,選擇Manage NuGet Packages菜單項(注意:.NET Framework的版本必須是4.5以上):ui
在打開的對話框中,搜索Roslyn,並將Roslyn安裝到項目中:spa
首先建立一個語法樹的訪問者,它繼承於Roslyn.Compilers.CSharp.SyntaxWalker,用於遍歷訪問C#的語法樹,它的實現以下:翻譯
class ExtractStringLiteralVisitor : SyntaxWalker { readonly List<string> literals = new List<string>(); public override void VisitLiteralExpression(LiteralExpressionSyntax node) { if (node.Kind == SyntaxKind.StringLiteralExpression) literals.Add(node.ToString()); base.VisitLiteralExpression(node); } public IEnumerable<string> Literals { get { return literals; } } }
而後,將上面第一段代碼文本保存到一個名爲source的字符串變量中(固然實際應用中也能夠從文件讀入源代碼),並使用SyntaxTree產生語法樹對象,以後使用上面的ExtractStringLiteralVisitor從根部對語法樹進行遍歷。因爲重寫的VisitLiteralExpression方法中保存了被訪問的文本節點,所以,當Visitor完成遍歷以後,便可經過Literals屬性得到全部的字符串常量。調試
var syntaxTree = SyntaxTree.ParseText(source); var root = syntaxTree.GetRoot(); var visitor = new ExtractStringLiteralVisitor(); visitor.Visit(root); foreach (var literal in visitor.Literals) Console.WriteLine(literal);
程序輸出以下:code
固然還可使用root.DescendantNodes方法來簡化上面的過程。我在例子中使用Visitor的目的就是爲了體現Roslyn的語法解析功能。
上面的輸入代碼是一段C#的程序,若是是VB.NET的源代碼,其實處理過程是同樣的,無非就是將引用的命名空間從Roslyn.Compilers.CSharp改成Roslyn.Compilers.VisualBasic。注意:Roslyn.Compilers.CSharp和Roslyn.Compilers.VisualBasic下都有SyntaxTree等類型的定義,但這些類型都是獨立的,並不是從某個基類繼承或實現了某些接口,在實際應用中還得注意這點。
Roslyn的應用場景應該仍是不少的,好比你們熟悉的FxCop,可以根據一些規則來檢測託管程序集是否知足這些規則,以保證質量。但FxCop很侷限,它須要使用反射,並根據程序集的調試信息PDB文件進行規則判斷,而對於源代碼自己的規範校驗就不太適用了。仔細思考,Roslyn卻可以在保證源代碼編寫規範方面,起到必定的做用。好比:
你們也能夠在實際中總結一些可以使用Roslyn的場景,我想只要合理利用,必定能在實際工做中幫助咱們提升效率,作到事半功倍。