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

C# 如何使用Roslyn获取用户输入表达式的类型?,c#,roslyn,C#,Roslyn,我的目标是实现一种方法Foo,以便: typeof(int)=Foo(“1+1”) 或 现在这个函数显然没有做任何有用的事情,这是因为它不工作。我得到一个“语法节点不在语法树中”异常。 我尝试过其他一些(相当可怕的)迭代,包括: var typeInfo = _semanticModel.GetTypeInfo(((FieldDeclarationSyntax)((CompilationUnitSyntax)syntaxTree.GetRoot()).Members.First()).Decl

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

typeof(int)=Foo(“1+1”)

现在这个函数显然没有做任何有用的事情,这是因为它不工作。我得到一个
“语法节点不在语法树中”
异常。 我尝试过其他一些(相当可怕的)迭代,包括:

var typeInfo = _semanticModel.GetTypeInfo(((FieldDeclarationSyntax)((CompilationUnitSyntax)syntaxTree.GetRoot()).Members.First()).Declaration.Variables.First().Initializer.Value);
它至少执行了,但我似乎无法从
GetTypeInfo
方法中获得任何实际的
TypeInfo

现在,即使我成功地得到了它,我也不确定我能用
TypeInfo
做什么;是否可以将其转换为
类型

因此,问题基本上归结为: 是否可以从字符串中获取
类型

如果是这样的话,我是不是走得很模糊?

您遇到的问题是
SyntaxFactory.ParseExpression(inputString)
正在创建一个新的节点,它与在
CSharpSyntaxTree.ParseText($“var x={inputString};”)中创建的节点不一样

这是一个这样工作的例子。我有这个项目文件:


Exe
网络48
8
还有这个控制台应用程序

使用系统;
使用System.Linq;
使用Microsoft.CodeAnalysis;
使用Microsoft.CodeAnalysis.CSharp;
使用Microsoft.CodeAnalysis.CSharp.Syntax;
班级计划{
静态void Main(字符串[]参数){
WriteLine(GetTypeForExpression(“new System.Collections.Generic.List()”));
}
公共静态类型GetTypeForExpression(string inputString){
var syntaxTree=CreateSyntaxTree(inputString,out var inputExpression);
//注意:要使语义分析发挥作用,您需要添加对任何其他程序集的引用
//有你关心的类型。
var mscorlib=MetadataReference.CreateFromFile(typeof(string.Assembly.Location));
var compilation=csharpcomilation.Create(“Test”).AddSyntaxTrees(syntaxTree).AddReferences(mscorlib);
var semanticModel=compilation.GetSemanticModel(syntaxTree);
var typeKind=semanticModel.GetTypeInfo(inputExpression).ConvertedType;
var fullyQualifiedMetadataName=typeKind.ToDisplayString(symboldDisplayFormat.FullyQualifiedFormat)
//C#关心全局命名空间,.NET反射API不关心
.Replace(“全局::”,“”)
//这可以处理C#中的泛型表示与反射API不同的情况
.Replace(typeKind.ToDisplayString(SymboldDisplayFormat.MinimalyQualifiedFormat)、typeKind.MetadataName);
返回typeKind.SpecialType开关
{
//关键字很难获取其元数据的完整名称
//我只想在这些特殊情况下
SpecialType.System_Object=>typeof(Object),
SpecialType.System_Boolean=>typeof(bool),
SpecialType.System_Char=>typeof(Char),
SpecialType.System_SByte=>typeof(SByte),
SpecialType.System_Byte=>typeof(字节),
SpecialType.System_Int16=>typeof(short),
SpecialType.System_UInt16=>typeof(ushort),
SpecialType.System_Int32=>typeof(int),
SpecialType.System_UInt32=>typeof(uint),
SpecialType.System_Int64=>typeof(长),
SpecialType.System_UInt64=>typeof(ulong),
SpecialType.System_Decimal=>typeof(十进制),
SpecialType.System_Single=>typeof(float),
SpecialType.System_Double=>typeof(Double),
SpecialType.System_String=>typeof(String),
_=>Type.GetType(fullyQualifiedMetadataName),
};
}
私有静态SyntaxTree CreateSyntaxTree(字符串输入字符串,输出表达式Syntax输入表达式){
//在有效的C#表达式上下文中创建树和节点
var tree=CSharpSyntaxTree.ParseText($“类C{{void M(){{{var x={inputString};}}}”);
//在树中查找表达式(而不是重新创建与此树无关的新节点)
inputExpression=tree.GetRoot()
.NodesandSelf的后代()
.OfType().Single()
.Variables.Single()
.Initializer.Value;
回归树;
}
}
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);
}
var typeInfo = _semanticModel.GetTypeInfo(((FieldDeclarationSyntax)((CompilationUnitSyntax)syntaxTree.GetRoot()).Members.First()).Declaration.Variables.First().Initializer.Value);