[英]How to use Roslyn SemanticModel to get TypeInfo with ScriptCompilation
我試圖提取TypeInfo以獲得動態腳本環境中可用成員的列表。
如果使用CSharpCompilation.Create(),則可以獲取成員列表,但是當我從CSharpScript狀態獲得編譯信息時,或使用CSharpCompilation.CreateScriptCompilation()時,都會出現異常“序列包含多個元素”。
此功能正常工作
public List<string> Test()
{
var code = @"
using System;
var i = 5; ";
var code2 = "i. ";
var parseOptions = new CSharpParseOptions(kind: SourceCodeKind.Script);
var syntaxTree = SyntaxFactory.ParseSyntaxTree(code, parseOptions);
var syntaxTree2 = SyntaxFactory.ParseSyntaxTree(code2, parseOptions);
var systemReference = MetadataReference.CreateFromFile(typeof(Int32).Assembly.Location);
var compilation = CSharpCompilation.Create("foo")
.AddReferences(systemReference)
.AddSyntaxTrees(syntaxTree)
.AddSyntaxTrees(syntaxTree2);
var semanticModel = compilation.GetSemanticModel(syntaxTree2);
var dotTextSpan = new TextSpan(code2.IndexOf("i.") + 1, 1);
var s = syntaxTree2.GetRoot().DescendantNodes(dotTextSpan).Last();
var memberAccessNode = (MemberAccessExpressionSyntax) s;
var lhsType = semanticModel.GetTypeInfo(memberAccessNode.Expression).Type;
var r = new List<string>();
foreach (var symbol in lhsType.GetMembers())
{
if (!symbol.CanBeReferencedByName
|| symbol.DeclaredAccessibility != Accessibility.Public
|| symbol.IsStatic)
continue;
r.Add(symbol.Name);
}
return r;
}
但是當使用CSharpScript代替時,出現異常
public List<string> Test2()
{
var code = @"
using System;
var i = 5; ";
var scriptOptions = ScriptOptions.Default;
scriptOptions.AddReferences(typeof(Int32).Assembly);
var scriptState = CSharpScript.RunAsync(code, scriptOptions).Result;
var code2 = "i. ";
var parseOptions = new CSharpParseOptions(kind: SourceCodeKind.Script);
var syntaxTree2 = SyntaxFactory.ParseSyntaxTree(code2, parseOptions);
var compilation = scriptState.Script.GetCompilation()
.AddSyntaxTrees(syntaxTree2);
var semanticModel = compilation.GetSemanticModel(syntaxTree2);
var dotTextSpan = new TextSpan(code2.IndexOf("i.") + 1, 1);
var s = syntaxTree2.GetRoot().DescendantNodes(dotTextSpan).Last();
var memberAccessNode = (MemberAccessExpressionSyntax)s;
var lhsType = semanticModel.GetTypeInfo(memberAccessNode.Expression).Type;
var r = new List<string>();
foreach (var symbol in lhsType.GetMembers())
{
if (!symbol.CanBeReferencedByName
|| symbol.DeclaredAccessibility != Accessibility.Public
|| symbol.IsStatic)
continue;
r.Add(symbol.Name);
}
return r;
}
知道如何讓它運行嗎?
編輯:這是異常的完整堆棧跟蹤。
" at System.Linq.Enumerable.SingleOrDefault[TSource](IEnumerable`1 source)\r\n at Microsoft.CodeAnalysis.CSharp.CSharpCompilation.IsSubmissionSyntaxTree(SyntaxTree tree)\r\n at Microsoft.CodeAnalysis.CSharp.BinderFactory.BinderFactoryVisitor.VisitCompilationUnit(CompilationUnitSyntax compilationUnit, Boolean inUsing, Boolean inScript)\r\n at Microsoft.CodeAnalysis.CSharp.BinderFactory.GetBinder(CSharpSyntaxNode node, Int32 position, CSharpSyntaxNode memberDeclarationOpt, Symbol memberOpt)\r\n at Microsoft.CodeAnalysis.CSharp.BinderFactory.GetBinder(CSharpSyntaxNode node, CSharpSyntaxNode memberDeclarationOpt, Symbol memberOpt)\r\n at Microsoft.CodeAnalysis.CSharp.SyntaxTreeSemanticModel.CreateMemberModel(CSharpSyntaxNode node)\r\n at System.Collections.Immutable.ImmutableInterlocked.GetOrAdd[TKey,TValue](ImmutableDictionary`2& location, TKey key, Func`2 valueFactory)\r\n at Microsoft.CodeAnalysis.CSharp.SyntaxTreeSemanticModel.GetMemberModel(CSharpSyntaxNode node)\r\n at Microsoft.CodeAnalysis.CSharp.SyntaxTreeSemanticModel.GetTypeInfoWorker(CSharpSyntaxNode node, CancellationToken cancellationToken)\r\n at Microsoft.CodeAnalysis.CSharp.CSharpSemanticModel.GetTypeInfo(ExpressionSyntax expression, CancellationToken cancellationToken)\r\n at Microsoft.CodeAnalysis.CSharp.CSharpExtensions.GetTypeInfo(SemanticModel semanticModel, ExpressionSyntax expression, CancellationToken cancellationToken)\r\n at ScriptEngine.ScriptingHost.Test2() in D:\\Source\\ScriptEngine\\ScriptingHost.cs:line 205"
腳本編譯只能有一個SyntaxTree 。
您應該改為將節點添加到原始SyntaxTree。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.