c# – 使用Rosyln将switch块重写为if / else

前端之家收集整理的这篇文章主要介绍了c# – 使用Rosyln将switch块重写为if / else前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我是roslyn的新手所以我正在寻找一些指针或示例代码来开始做我想要的.

我有很多与此类似的代码(它是由工具生成的)

switch (boolVariable)
{
    case false:
    {
        str = "blahblah";
        break;
    }
    case true:
    {
        str = "somethingelse";
        break;
    }
    default:
    {
        str = "ughthiswouldnevergethit";
        break;
    }
}

我想要做的是检测然后将语法重写为更高效和开发人员友好的东西

if(boolVariable)
{
   str = "somethingelse";
}
else
{
   str = "blahblah";
}

基本上我想要优化所有布尔值的开关.

解决方法

你必须使用CSharpSyntaxRewriter,下面是实现它的代码(简单的情况下,你可以从中扩展)

(您应该下载Syntax Visualizer扩展或转到简单的在线版本CSharp SyntaxTree 以了解有关语法树的更多信息)

string code = ReadText("Case6.cs"); // get source code as string for a class
var tree = CSharpSyntaxTree.ParseText(code);
CompilationUnitSyntax root = (CompilationUnitSyntax)tree.GetRoot();
Compilation compilation = CSharpCompilation.Create("assembly",SyntaxTrees: new[] { tree },references: new[]
{
    mscorlib = MetadataReference.CreateFromAssembly(typeof(object).Assembly),MetadataReference.CreateFromAssembly(typeof(Stack<>).Assembly)
});

var semanticModel = compilation.GetSemanticModel(tree);
var myRewriter = new MyRewriter(semanticModel);
var result = myRewriter.Visit(tree.GetRoot());
var str = result.ToString();

// below are classes for Rewriter
public class MyRewriter : CSharpSyntaxRewriter
{
    private SemanticModel semanticModel;

    public MyRewriter(SemanticModel semanticModel)
    {
        this.semanticModel = semanticModel;
    }

    public override SyntaxNode VisitSwitchStatement(SwitchStatementSyntax node)
    {
        var result =  base.VisitSwitchStatement(node);

        // detect your case:
        // first check if the expression in switch is bool type?
        var typeInfo = semanticModel.GetTypeInfo(node.Expression);

        if(typeInfo.Type.SpecialType != SpecialType.System_Boolean)
        {
            return result;
        }

        // okie we make the conversion here
        // find true statement
        var trueSection = node.Sections
                .First(f => f.Labels.First().ToString().Contains("true"));
        var falseSection = node.Sections
                .First(f => f.Labels.First().ToString().Contains("false"));

        var trueStatement = trueSection.Statements.Count == 1
                        ? trueSection.Statements.First()
                        : SyntaxFactory.Block(trueSection.Statements);
        var falseStatement = falseSection.Statements.Count == 1
                        ? falseSection.Statements.First()
                        : SyntaxFactory.Block(falseSection.Statements);

        var ifStatement = SyntaxFactory.IfStatement(node.Expression,trueStatement,SyntaxFactory.ElseClause(falseStatement));

        //NOTE that: this class will remove all break statements
        // it will not be correct if break in loop,you can base on that to 
        // write more accurately
        var breakRemover = new BreakRemover();

        result = breakRemover.Visit(ifStatement);

        return result;
    }
}

public class BreakRemover : CSharpSyntaxRewriter
{
    public override SyntaxNode VisitBreakStatement(BreakStatementSyntax node)
    {
        // should add further check to make sure break statement is in
        // switch,the idea is find closest ancestor must be switch (not
        // for,foreach,while,dowhile)
        return SyntaxFactory.EmptyStatement();
    }
}

猜你在找的C#相关文章