2017-03-29 18 views
1

私は、roslynを使用してアセンブリを動的に構築しようとしており、後で ASP.NET CORE 'AddApplicationParts'拡張メソッドからロードしています。 。他のプロジェクトのファイルからコンパイルされたroslynへの参照

他のプロジェクトから.csファイルを外部に読み込んでいますが、そこではうまくいきます。

ここでコードはありますが、私はすべて動作するようになっていますが、外部プロジェクトから「参照」をロードする方法を理解できないようです。メタデータファイルから「参照の追加」を試みました。

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; 
     } 
    } 
} 

外部ファイルが別のasp.netコア事業であるが、4.6.2フレームワークを使用して、vs2017コアテンプレートから新鮮始めました。 !!

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

あなたは何のエラーを得るのですか?より多くの参照を追加する必要があります。 – SLaks

答えて

0

問題は、ファイルをコンパイルするときにのみmscorlibを参照しているということですが、あなたは、ファイルが依存するすべてのアセンブリを参照する必要があります。一度に1つのアセンブリを実行しようとすることもできますが、より良い選択肢は、必要なすべての情報を含む2番目のcsprojがあるという事実を利用することです。何とかそこから情報を取得するだけです。

これを行うには、MSBuildを使用できます。 Microsoft.BuildMicrosoft.Build.Tasks.Coreパッケージを参照して、(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

新しいProjectInstance(projectFileName)にcsprojへのパスを渡そうとすると、 'system.ioファイルが見つかりませんでした。 – Aflred

関連する問題