zoukankan      html  css  js  c++  java
  • 使用Microsoft Roslyn提取C#和VB.NET源代码中的字符串常量

    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#编译器,但我想性能至少不会比原来的实现方式差。”

    有关Roslyn的内容,可以参考以下链接:

    让我们先睹为快,了解一下Roslyn的一个具体应用:提取C#和VB.NET代码中的字符串常量。

    字符串常量的提取

    先看下面的一段代码:

    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以上):

    image

    在打开的对话框中,搜索Roslyn,并将Roslyn安装到项目中:

    SNAGHTMLdbda5b

    首先创建一个语法树的访问者,它继承于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);
    

    程序输出如下:

    image

    当然还可以使用root.DescendantNodes方法来简化上面的过程。我在例子中使用Visitor的目的就是为了体现Roslyn的语法解析功能。

    对VB.NET语言的应用

    上面的输入代码是一段C#的程序,如果是VB.NET的源代码,其实处理过程是一样的,无非就是将引用的命名空间从Roslyn.Compilers.CSharp改为Roslyn.Compilers.VisualBasic。注意:Roslyn.Compilers.CSharp和Roslyn.Compilers.VisualBasic下都有SyntaxTree等类型的定义,但这些类型都是独立的,并非从某个基类继承或实现了某些接口,在实际应用中还得注意这点。

    应用场景的思考

    Roslyn的应用场景应该还是很多的,比如大家熟悉的FxCop,能够根据一些规则来检测托管程序集是否满足这些规则,以保证质量。但FxCop很局限,它需要使用反射,并根据程序集的调试信息PDB文件进行规则判断,而对于源代码本身的规范校验就不太适用了。仔细思考,Roslyn却能够在保证源代码编写规范方面,起到一定的作用。比如:

    • 对定义的变量名、函数名等进行拼写检查
    • 检查注释语句中的拼写错误
    • 检查变量、函数等的命名规范
    • XML文档的自动化翻译(可以借助Bing Translate、Google Translate的API实现自动化翻译),等等

    大家也可以在实际中总结一些能够使用Roslyn的场景,我想只要合理利用,一定能在实际工作中帮助我们提高效率,做到事半功倍。

  • 相关阅读:
    Azure 虚拟机安全加固整理
    AzureARM 使用 powershell 扩容系统磁盘大小
    Azure Linux 云主机使用Root超级用户登录
    Open edX 配置 O365 SMTP
    powershell 根据错误GUID查寻错误详情
    azure 创建redhat镜像帮助
    Azure Powershell blob中指定的vhd创建虚拟机
    Azure Powershell 获取可用镜像 PublisherName,Offer,Skus,Version
    Power BI 连接到 Azure 账单,自动生成报表,可刷新
    Azure powershell 获取 vmSize 可用列表的命令
  • 原文地址:https://www.cnblogs.com/daxnet/p/3378193.html
Copyright © 2011-2022 走看看