2017-03-29 4 views
1

Ich versuche, eine Assembly dynamisch zu erstellen, mit Roslyn, und später von der ASP.NET CORE 'AddApplicationParts' Erweiterungsmethode in der Startphase meiner Webanwendung geladen werden .Verweise auf Roslyn kompiliert von Datei aus einem anderen Projekt

Ich lade eine CS-Datei extern von einem anderen Projekt, wo es gut funktioniert.

Hier ist der Code, ich habe alles zu arbeiten, aber ich kann nicht herausfinden, wie 'Referenzen' aus dem externen Projekt zu laden, habe ich versucht, die so genannten 'add references' aus metadatfile aber kein Glück.

using System; 
using System.Collections.Generic; 
using System.IO; 
using System.Linq; 
using Microsoft.AspNetCore.Hosting; 
using Microsoft.CodeAnalysis.CSharp; 
using Microsoft.CodeAnalysis; 
using Microsoft.CodeAnalysis.CSharp.Syntax; 
using System.Reflection; 
using System.Collections.Immutable; 

namespace WebApplication1 
{ 



    public class Program 
    { 
     public static void Main(string[] args) 
     { 
      var host = new WebHostBuilder() 
       .UseKestrel() 
       .UseContentRoot(Directory.GetCurrentDirectory()) 
       .UseIISIntegration() 
       .UseStartup<Startup>() 
       .UseApplicationInsights() 
       .Build(); 

      Pr2.Main2(); 

      host.Run(); 
     } 
    } 



    public class Pr2 
    { 
     public static void Main2() 
     { 
      string code = File.ReadAllText(@"c:\users\victor\documents\visual studio 2017\Projects\WebApplication2\WebApplication2\Controllers\HomeController.cs"); 
      SyntaxTree tree = SyntaxFactory.ParseSyntaxTree(code); 

      CSharpCompilation compilation = CreateCompilation(tree); 
      SemanticModel model = compilation.GetSemanticModel(tree); 

      ShowLocalDeclarations(tree, model); 
      ShowDiagnostics(compilation); 
      ExecuteCode(compilation); 

     } 

     private static void ShowLocalDeclarations(SyntaxTree tree, SemanticModel model) 
     { 
      IEnumerable<LocalDeclarationStatementSyntax> locals = tree.GetRoot() 
          .DescendantNodes() 
          .OfType<LocalDeclarationStatementSyntax>(); 

      foreach (var node in locals) 
      { 
       Microsoft.CodeAnalysis.TypeInfo type = model.GetTypeInfo(node.Declaration.Type); 
       Console.WriteLine("{0} {1}", type.Type, node.Declaration); 
      } 
     } 

     private static Assembly ExecuteCode(CSharpCompilation compilation) 
     { 
      Assembly roRet; 
      using (var stream = new MemoryStream()) 
      { 
       compilation.Emit(stream); 

       roRet = Assembly.Load(stream.GetBuffer()); 
      } 

      return roRet; 
     } 

     private static void ShowDiagnostics(CSharpCompilation compilation) 
     { 
      ImmutableArray<Diagnostic> diagnostics = compilation.GetDiagnostics(); 
      foreach (var diagnostic in diagnostics) 
      { 
       // OVER HERE WE SEE THE ERRORS. 
       Console.WriteLine(diagnostic.ToString()); 
      } 
     } 

     private static CSharpCompilation CreateCompilation(SyntaxTree tree) 
     { 
      CSharpCompilationOptions options = new CSharpCompilationOptions(
              OutputKind.DynamicallyLinkedLibrary); 

      PortableExecutableReference reference = MetadataReference.CreateFromFile(typeof(object).Assembly.Location); 

      CSharpCompilation compilation = 
       CSharpCompilation.Create("test") 
           .WithOptions(options) 
           .AddSyntaxTrees(tree) 
           .AddReferences(reference); 
      return compilation; 
     } 
    } 
} 

Die externe Datei in einem anderen asp.net Kernprojekt ist, gestartet von vs2017 Kernvorlagen frisch, den4.6.2 Framework. !!

using Microsoft.AspNetCore.Mvc; 

namespace WebApplication2.Controllers 
{ 
    public class TestController : Controller 
    { 
     public IActionResult Index() 
     { 
      return View(); 
     } 

     public IActionResult About() 
     { 
      ViewData["Message"] = "Your application description page."; 

      return View(); 
     } 

     public IActionResult Contact() 
     { 
      ViewData["Message"] = "Your contact page."; 

      return View(); 
     } 

     public IActionResult Error() 
     { 
      return View(); 
     } 
    } 
} 
+0

Welche Fehler bekommen Sie? Sie müssen weitere Referenzen hinzufügen. – SLaks

Antwort

0

Das Problem ist, dass Sie nur mscorlib sind Referenzierung, wenn die Datei zu kompilieren, aber Sie müssen alle Baugruppen der Datei hängt von verweisen. Sie könnten versuchen, diese eine Assembly zu einer Zeit zu machen, aber ich denke, eine bessere Option ist, die Tatsache auszunutzen, dass Sie eine zweite csproj haben, die alle Informationen enthält, die Sie brauchen. Sie müssen nur irgendwie die Informationen von dort bekommen.

Um dies zu tun, können Sie MSBuild verwenden. Verweisen Sie auf die Microsoft.Build und Microsoft.Build.Tasks.Core Pakete und verwenden Sie dann diesen Code (angepasst von this answer):

private static IEnumerable<string> GetReferences(string projectFileName) 
{ 
    var projectInstance = new ProjectInstance(projectFileName); 
    var result = BuildManager.DefaultBuildManager.Build(
     new BuildParameters(), 
     new BuildRequestData(projectInstance, new[] 
     { 
      "ResolveProjectReferences", 
      "ResolveAssemblyReferences" 
     })); 

    IEnumerable<string> GetResultItems(string targetName) 
    { 
     var buildResult = result.ResultsByTarget[targetName]; 
     var buildResultItems = buildResult.Items; 

     return buildResultItems.Select(item => item.ItemSpec); 
    } 

    return GetResultItems("ResolveProjectReferences") 
     .Concat(GetResultItems("ResolveAssemblyReferences")); 
} 

// in Main2 
var references = GetReferences(@"C:\code\tmp\roslyn references\WebApplication2\WebApplication2.csproj"); 

CSharpCompilation compilation = CreateCompilation(tree, references); 

// in CreateCompilation 
CSharpCompilation compilation = 
    CSharpCompilation.Create("test") 
     .WithOptions(options) 
     .AddSyntaxTrees(tree) 
     .AddReferences(references.Select(path => MetadataReference.CreateFromFile(path))); 
+0

Ich erhalte eine 'system.io Datei nicht gefunden Ausnahme, wenn ich versuche, den Pfad zu einem csproj zu neuen ProjectInstance (projectFileName) zu übergeben; – Aflred

Verwandte Themen