简体   繁体   中英

How to get the type of an argument in Roslyn?

So I am trying to know the type of some variables in the argument when calling a method. Such as in:

class Program
{
    static void Main(string[] args)
    {
        string a = "astring"
        string.Format("zzzz{0}", a);
    }
}

So I want to know the type of variable a in string.Format("zzzz{0}, a"); I am trying to change some code so I am using rewriter and here is what I got:

public class CustomFormatRewriter : CSharpSyntaxRewriter{

    public override SyntaxNode VisitInvocationExpression(InvocationExpressionSyntax rootNode){
        if (null != rootNode){
            var arguments =
            from n in secondNode.DescendantNodes()
            where (n.Kind() == SyntaxKind.Argument)
            select n;

            foreach (var argument in arguments)
            {
               var compilation = CSharpCompilation.Create("arg")
                                                            .AddReferences(MetadataReference.CreateFromFile(typeof(object).Assembly.Location))
                                                     .AddSyntaxTrees(rootNode.SyntaxTree);

               var model = compilation.GetSemanticModel(rootNode.SyntaxTree);
               var symbolInfo = model.GetSymbolInfo(argument);
               Console.WriteLine(symbolInfo.Symbol);
            }
        }  
        return rootNode;
    }

}

But the symbolInfo.Symbol I got is null.

Any idea? Thanks!!

If you want to know the type of something, you can call SemanticModel.GetTypeInfo . This works for all expressions, not just ones that are directly a variable. So not only will passing the expression for a give you the type of a , but a.SomeMethod() will figure out which overload of SomeMethod is being called on a , and will give you the type of the return. If your expression is just a number, it'll tell you the type is Int32.

GetSymbolInfo only works if the thing you're passing in directly is a reference to a symbol, ie it's the name of a local or field or something. In your case, the first argument that's a string isn't going to give you a symbol. It has a type (notably, System.String), but it's not a symbol.

Okay I found out why I am always getting null. Post just in case someone may find it helpful in the future.

I found this post very helpful in identifying my problem. So it turns out I am not checking type on the correct "level", as I call it. I used the method in the post(In the syntax visualizer, right click a node -> view typeSymbol) to check for the type of my argument. I found that if I check at "Argument", then there is nothing, which explains why I got null. And if I check the node at the level under the "Argument", it gives you the right type.

So I changed my code to:

var typeInfo = model.GetTypeInfo(argument.ChildNodes().First());
Console.WriteLine(typeInfo);

And it works.

将其转换为ILocalSymbol ,然后读取Type属性。

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM