如何使用Roslyn获取用户输入表达式的类型?

Abarnybox

我的目标是实现一种方法Foo,以便:

typeof(int) == Foo("1 + 1")

要么

typeof(List<int>) == Foo("new List<int>()")

请勿执行字符串中的表达式,这一点很重要,因此我正在尝试使用Roslyn来实现这一点。到目前为止,我已经:

public Type Foo(string inputString)
{
   var syntaxTree = CSharpSyntaxTree.ParseText($"var x = {inputString};");
   var compilation = CSharpCompilation.Create("Test").AddSyntaxTrees(syntaxTree);
   var semanticModel = compilation.GetSemanticModel(syntaxTree);

   var typeInfo = semanticModel.GetTypeInfo(SyntaxFactory.ParseExpression(inputString));
   return typeof(string);
}

现在,该函数当前显然没有任何用处,这是因为它不起作用。我有一个"Syntax node is not within syntax tree"例外。我尝试了其他一些(非常恐怖的)迭代,包括:

var typeInfo = _semanticModel.GetTypeInfo(((FieldDeclarationSyntax)((CompilationUnitSyntax)syntaxTree.GetRoot()).Members.First()).Declaration.Variables.First().Initializer.Value);

至少执行过,但是我似乎无法TypeInfo从该GetTypeInfo方法中获得任何实际信息...

现在,即使我确实设法做到了,我也不知道我可以用TypeInfo;做些什么能不能变成一个Type

因此,从本质上讲,问题可以归结为:是否可以Type从字符串中获取a 如果是的话,我是否还在朝着正确的方向模糊地走?

乔纳森·马洛夫(Jonathon Marolf)

您遇到的问题是SyntaxFactory.ParseExpression(inputString)正在完全创建一个新节点,并且与在其中创建的节点不同CSharpSyntaxTree.ParseText($"var x = {inputString};")

这是此工作的示例。我有这个项目文件:

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net48</TargetFramework>
    <LangVersion>8.0</LangVersion>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Microsoft.CodeAnalysis.Analyzers" Version="3.0.0" PrivateAssets="all" />
    <PackageReference Include="Microsoft.CodeAnalysis.CSharp.Workspaces" Version="3.5.0" />
  </ItemGroup>

</Project>

和这个控制台应用程序

using System;
using System.Linq;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;

class Program {
    static void Main(string[] args) {
        Console.WriteLine(GetTypeForExpression("new System.Collections.Generic.List<System.Int32>()"));
    }

    public static Type GetTypeForExpression(string inputString) {
        var syntaxTree = CreateSyntaxTree(inputString, out var inputExpression);
        // NOTE for semantic analysis to work you will need to add references to any other assemblies
        // that have types you care about.
        var mscorlib = MetadataReference.CreateFromFile(typeof(string).Assembly.Location);
        var compilation = CSharpCompilation.Create("Test").AddSyntaxTrees(syntaxTree).AddReferences(mscorlib);
        var semanticModel = compilation.GetSemanticModel(syntaxTree);
        var typeKind = semanticModel.GetTypeInfo(inputExpression).ConvertedType;
        var fullyQualifiedMetadataName = typeKind.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat)
            // C# cares about the global namespace, .NET reflection APIs do not
            .Replace("global::", "")
            // This handles situations where the generic representation is different in C# from the reflection APIs
            .Replace(typeKind.ToDisplayString(SymbolDisplayFormat.MinimallyQualifiedFormat), typeKind.MetadataName);
        return typeKind.SpecialType switch
        {
            // keywords are hard to get the full metadata name for
            // I would just special case these
            SpecialType.System_Object => typeof(object),
            SpecialType.System_Boolean => typeof(bool),
            SpecialType.System_Char => typeof(char),
            SpecialType.System_SByte => typeof(sbyte),
            SpecialType.System_Byte => typeof(byte),
            SpecialType.System_Int16 => typeof(short),
            SpecialType.System_UInt16 => typeof(ushort),
            SpecialType.System_Int32 => typeof(int),
            SpecialType.System_UInt32 => typeof(uint),
            SpecialType.System_Int64 => typeof(long),
            SpecialType.System_UInt64 => typeof(ulong),
            SpecialType.System_Decimal => typeof(decimal),
            SpecialType.System_Single => typeof(float),
            SpecialType.System_Double => typeof(double),
            SpecialType.System_String => typeof(string),
            _ => Type.GetType(fullyQualifiedMetadataName),
        };
    }

    private static SyntaxTree CreateSyntaxTree(string inputString, out ExpressionSyntax inputExpression) {
        // Creates a tree and nodes in a valid C# expression context
        var tree = CSharpSyntaxTree.ParseText($"class C{{void M(){{var x = {inputString};}}}}");
        // Finds the expression inside the tree (instead of re-creating a new node unrelated to this tree)
        inputExpression = tree.GetRoot()
            .DescendantNodesAndSelf()
            .OfType<VariableDeclarationSyntax>().Single()
            .Variables.Single()
            .Initializer.Value;
        return tree;
    }
}

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

获取用于表达式的通用类型的属性类型

来自分类Dev

在Roslyn中获取表达式类型的结果

来自分类Dev

使用JavaScript正则表达式从网址获取用户和推特ID

来自分类Dev

如何编写正则表达式以仅从此字符串输出中获取用户

来自分类Dev

在路径正则表达式或pathlib Python中获取用户

来自分类Dev

如何使用ReactJS获取用户输入字段的值?

来自分类Dev

我如何使用数组来获取用户输入

来自分类Dev

如何使用 HTML 获取用户输入以在 JS 中处理?

来自分类Dev

使用正则表达式验证用户输入

来自分类Dev

使用正则表达式限制用户输入

来自分类Dev

如何使用正则表达式解析用户输入并从结果中生成新变量

来自分类Dev

VBA 如何在单元格中的用户输入上使用正则表达式

来自分类Dev

使用decltype获取表达式的类型,而不使用const

来自分类Dev

使用正则表达式从推文中抓取用户名

来自分类Dev

如何在Roslyn中限制对外部类型的表达式访问?

来自分类Dev

获取类型名称或表达式的类型

来自分类Dev

条件表达式-如何在条件表达式中获取报告类型

来自分类Dev

从Swift REPL,如何获取表达式的静态类型?

来自分类Dev

如何获取ArrayLength类型表达式的MemberInfo?

来自分类Dev

如何获取ArrayLength类型表达式的MemberInfo?

来自分类Dev

IBM Watson - 如何使用正则表达式从用户获取登录信息

来自分类Dev

如何获取用户输入-批处理?

来自分类Dev

PL/SQL 如何获取用户输入

来自分类Dev

使用Lambda表达式获取属性或类型名称

来自分类Dev

使用正则表达式获取 SNMP 陷阱类型

来自分类Dev

使用MessageBox获取用户输入?

来自分类Dev

使用Rascal获取用户输入

来自分类Dev

使用MessageBox获取用户输入?

来自分类Dev

使用PHP获取用户输入

Related 相关文章

  1. 1

    获取用于表达式的通用类型的属性类型

  2. 2

    在Roslyn中获取表达式类型的结果

  3. 3

    使用JavaScript正则表达式从网址获取用户和推特ID

  4. 4

    如何编写正则表达式以仅从此字符串输出中获取用户

  5. 5

    在路径正则表达式或pathlib Python中获取用户

  6. 6

    如何使用ReactJS获取用户输入字段的值?

  7. 7

    我如何使用数组来获取用户输入

  8. 8

    如何使用 HTML 获取用户输入以在 JS 中处理?

  9. 9

    使用正则表达式验证用户输入

  10. 10

    使用正则表达式限制用户输入

  11. 11

    如何使用正则表达式解析用户输入并从结果中生成新变量

  12. 12

    VBA 如何在单元格中的用户输入上使用正则表达式

  13. 13

    使用decltype获取表达式的类型,而不使用const

  14. 14

    使用正则表达式从推文中抓取用户名

  15. 15

    如何在Roslyn中限制对外部类型的表达式访问?

  16. 16

    获取类型名称或表达式的类型

  17. 17

    条件表达式-如何在条件表达式中获取报告类型

  18. 18

    从Swift REPL,如何获取表达式的静态类型?

  19. 19

    如何获取ArrayLength类型表达式的MemberInfo?

  20. 20

    如何获取ArrayLength类型表达式的MemberInfo?

  21. 21

    IBM Watson - 如何使用正则表达式从用户获取登录信息

  22. 22

    如何获取用户输入-批处理?

  23. 23

    PL/SQL 如何获取用户输入

  24. 24

    使用Lambda表达式获取属性或类型名称

  25. 25

    使用正则表达式获取 SNMP 陷阱类型

  26. 26

    使用MessageBox获取用户输入?

  27. 27

    使用Rascal获取用户输入

  28. 28

    使用MessageBox获取用户输入?

  29. 29

    使用PHP获取用户输入

热门标签

归档