2016-04-30 69 views
1

我正在爲我的應用程序添加腳本編寫的可能性。 Init方法加載腳本,編譯它並調用腳本Init方法。我希望能夠將Visual Studio調試器附加到我的應用程序,並在IDE中以通常的方式在腳本中添加斷點。爲動態編譯的程序集加載符號

Visual Studio說:加載'i0uu5bcn.vhy'。找不到或打開PDB文件。

如果使用類似下面的斷點:System.Diagnostics.Debugger.Break();

public static string[] Init(string scriptPath, params object[] parameters) 
     { 
      List<string> errors = new List<string>(); 

      SyntaxTree syntaxTree = CSharpSyntaxTree.ParseText(File.ReadAllText(scriptPath), null, scriptPath); 

      SyntaxTree encoded = CSharpSyntaxTree.Create(syntaxTree.GetRoot() as CSharpSyntaxNode, null, scriptPath, System.Text.Encoding.UTF8); 

      string assemblyName = Path.GetRandomFileName(); 

      MetadataReference[] references = new MetadataReference[] 
      { 
       MetadataReference.CreateFromFile(typeof(object).Assembly.Location), 
       MetadataReference.CreateFromFile(typeof(Enumerable).Assembly.Location) 
      }; 

      CSharpCompilation compilation = CSharpCompilation.Create(
       assemblyName, 
       syntaxTrees: new[] { encoded }, 
       references: references, 
       options: new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary)); 

      Assembly finalAssembly = null; 

      using (var symbols = new MemoryStream()) 
      { 
       using (var ms = new MemoryStream()) 
       { 
        EmitResult result = compilation.Emit(ms, symbols); 

        if (!result.Success) 
        { 
         IEnumerable<Diagnostic> failures = result.Diagnostics.Where(diagnostic => 
          diagnostic.IsWarningAsError || 
          diagnostic.Severity == DiagnosticSeverity.Error); 

         foreach (Diagnostic diagnostic in failures) 
         { 
          errors.Add($"{diagnostic.Id}: {diagnostic.GetMessage()}"); 
         } 
        } 
        else 
        { 
         ms.Seek(0, SeekOrigin.Begin); 
         symbols.Seek(0, SeekOrigin.Begin); 

         finalAssembly = Assembly.Load(ms.ToArray(), symbols.ToArray()); 

         Type type = finalAssembly.DefinedTypes.First().AsType(); 
         object obj = Activator.CreateInstance(type); 
         type.InvokeMember("Init", 
          BindingFlags.Default | BindingFlags.InvokeMethod, 
          null, 
          obj, 
          parameters); 
        } 
       } 
      } 

      return errors.ToArray(); 
     } 

回答

2

確保該文件實際上是UTF8編碼的。編碼用於獲取生成PDB時使用的散列函數的輸入字節。請注意,Encoding.UTF8假定文件有BOM

可以使用SourceLink轉儲從生成PDB(它保存到硬盤的第一個...)校驗:

sourcelink checksums -p <pdbfile> 

您可以針對散列轉儲比較您的腳本文件中的值的您在代碼中計算的源文件。除非這兩者不匹配,否則Visual Studio的調試器將不會正確拾取腳本文件。

另請注意,如果您使用SourceText.From(Stream, Encoding),它會嘗試detect the correct encodingfor you

所以,如果我的預感是正確的,得到了​​SourceTree這應該解決您的問題,以及:

SyntaxTree encoded; 
using(var stream = File.OpenRead(scriptPath)) 
{ 
    SourceText text = SourceText.From(stream, Encoding.UTF8); 
    encoded = CSharpSyntaxTree.ParseText(text, null, scriptPath); 
}