2017-01-11 11 views
0

Я пытаюсь извлечь TypeInfo, чтобы получить список доступных членов в среде динамического сценария.Как использовать Roslyn SemanticModel для получения TypeInfo с ScriptCompilation

Я могу получить список членов, если я использую CSharpCompilation.Create(), но когда я получаю компиляцию из состояния CSharpScript или использую CSharpCompilation.CreateScriptCompilation(), я получаю исключение ». Sequence содержит больше, чем один элемент ".

Эта функция работает отлично

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" 
+0

Что такое трассировка стека? – SLaks

+0

StackTrace = "в System.Linq.Enumerable.SingleOrDefault [TSource] (источник IEnumerable'1) \ r \ n в Microsoft.CodeAnalysis.CSharp.CSharpCompilation.IsSubmissionSyntaxTree (дерево синтаксиса) \ r \ n в Microsoft.CodeAnalysis.CSharp. BinderFactory.BinderFactoryVisitor.VisitComp ... – user978281

+0

Пожалуйста, включите полную проверку стека в виде кода в свой вопрос. – SLaks

ответ