【问题标题】:Error when compiling .net core app using Roslyn使用 Roslyn 编译 .net 核心应用程序时出错
【发布时间】:2019-08-13 05:41:58
【问题描述】:

我正在生成代码,然后使用 Roslyn 进行编译。它适用于框架,但是当我尝试对核心做同样的事情时,它失败了。

错误是:

程序集中类型“System.Func`2”的类型转发器 'System.Runtime' 导致循环

下面是失败的代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Data;

namespace CoreTest
{

    public class TestCore
    {
        public void Test()
        {
            var dt = new DataTable();
            dt.Columns.Add("A");

            var numbers = new List<int>();
            var items = numbers.Where(q => q > 5).ToList();
        }
    }

}

这是编译它的代码:

using System;
using System.CodeDom.Compiler;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Microsoft.CodeDom.Providers.DotNetCompilerPlatform;

namespace CompilerTest
{

    public class BuildCodeCore
    {
        private string _CoreAssemblyFolder = @"C:\Program Files\dotnet\sdk\NuGetFallbackFolder\microsoft.netcore.app\2.1.0\ref\netcoreapp2.1";

        public BuildCodeCore() { }

        public List<string> Files { get; set; } = new List<string>();
        public string OutputFileNameAndPath { get; set; }
        public string ReferencedAssembliesPath { get; set; }

        public void BuildCore()
        {
            string assemblyFolder = _CoreAssemblyFolder;
            string coreAssemblyFileName = "System.Runtime.dll";

            var assemblies = GetAssembliesInFolder(assemblyFolder);
            if (!string.IsNullOrWhiteSpace(ReferencedAssembliesPath))
            {
                assemblies.AddRange(GetAssembliesInFolder(ReferencedAssembliesPath));
            }

            CSharpCodeProvider codeProvider = new CSharpCodeProvider();
            ICodeCompiler icc = codeProvider.CreateCompiler();

            CompilerParameters parameters = new CompilerParameters();
            parameters.CoreAssemblyFileName = coreAssemblyFileName;
            parameters.ReferencedAssemblies.AddRange(assemblies.ToArray());
            parameters.GenerateExecutable = false;
            parameters.OutputAssembly = OutputFileNameAndPath;

            CompilerResults results = icc.CompileAssemblyFromFileBatch(parameters, Files.ToArray());

            if (results.Errors.Count > 0)
            {
                foreach (CompilerError error in results.Errors)
                {
                    Console.WriteLine(error);
                }
            }

        }

        private List<string> GetAssembliesInFolder(string assemblyPath)
        {
            var files = Directory.GetFiles(assemblyPath, "*.dll");

            return files.ToList();
        }

    }
}

我指向的是核心 dll 的 NuGetFallbackFolder 文件夹,而其他来自 nuget 的文件夹,System.Data.DataSetExtensions.dllSystem.Data.SqlClient.dll 是来自 Visual Studio 中工作项目的文件夹。

如果我注释掉两个 DataTable 行和 using System.Data,它可以工作。 如果我注释掉数字和项目行,它会起作用。

我在这里错过了什么?

【问题讨论】:

    标签: c# .net-core roslyn


    【解决方案1】:

    事实证明,CompileAssemblyFromFileBatch 不适用于核心应用程序。

    我不得不改用 CSharpCompilation 和 Emit 方法。这适用于编译框架和核心。

    using System;
    using System.Collections.Generic;
    using System.IO;
    using System.Linq;
    using Microsoft.CodeAnalysis;
    using Microsoft.CodeAnalysis.CSharp;
    
    namespace CompilerTest
    {
        public class BuildEmit
        {
            private string _CoreAssemblyFolder = @"C:\Program Files\dotnet\sdk\NuGetFallbackFolder\microsoft.netcore.app\2.1.0\ref\netcoreapp2.1";
            private string _FrameworkAssemblyFolder = @"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.2";
    
            public BuildEmit() { }
    
            public List<string> Files { get; set; } = new List<string>();
            public string OutputFileNameAndPath { get; set; }
            public string ReferencedAssembliesPath { get; set; }
            public CompilerType Compiler { get; set; }
    
    
            public void Build()
            {
                string assemblyFolder = string.Empty;
                string coreAssemblyFileName = string.Empty;
                switch (Compiler)
                {
                    case CompilerType.Framework:
                        assemblyFolder = _FrameworkAssemblyFolder;
                        coreAssemblyFileName = "mscorlib.dll";
                        break;
                    case CompilerType.Core:
                        assemblyFolder = _CoreAssemblyFolder;
                        coreAssemblyFileName = "System.Runtime.dll";
                        break;
                }
                PortableExecutableReference objectDef = MetadataReference.CreateFromFile(Path.Combine(assemblyFolder, coreAssemblyFileName));
    
                List<SyntaxTree> syntaxes = new List<SyntaxTree>();
                foreach (string codeFile in Files)
                {
                    var code = File.ReadAllText(codeFile);
                    var tree = CSharpSyntaxTree.ParseText(code);
                    syntaxes.Add(tree);
                }
    
                var references = new List<PortableExecutableReference>();
                references.Add(objectDef);
    
                var assemblies = FilterInvalidAssembies(GetAssembliesInFolder(assemblyFolder));
                if (!string.IsNullOrWhiteSpace(ReferencedAssembliesPath))
                {
                    assemblies.AddRange(GetAssembliesInFolder(ReferencedAssembliesPath));
                }
                foreach (string item in assemblies)
                {
                    var reference = MetadataReference.CreateFromFile(item);
                    references.Add(reference);
                }
                var compilation = CSharpCompilation.Create(Path.GetFileNameWithoutExtension(OutputFileNameAndPath), syntaxes, references);
                compilation = compilation.WithOptions(new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary));
    
                var emitResult = compilation.Emit(OutputFileNameAndPath);
    
                if (!emitResult.Success)
                {
                    foreach (var diagnostic in emitResult.Diagnostics)
                    {
                        Console.WriteLine(diagnostic.ToString());
                    }
                    File.Delete(OutputFileNameAndPath);
                }
            }
    
            private void RemoveStringFromList(List<string> items, string contains)
            {
                var item = items.Where(q => q.Contains(contains)).Select(q => q).FirstOrDefault();
                if (item != null)
                {
                    items.Remove(item);
                }
            }
    
            private List<string> FilterInvalidAssembies(List<string> files)
            {
                RemoveStringFromList(files, "System.EnterpriseServices.Wrapper.dll");
                RemoveStringFromList(files, "System.EnterpriseServices.Thunk.dll");
                //RemoveStringFromList(files, "mscorlib.dll");
                return files;
            }
    
            private List<string> GetAssembliesInFolder(string assemblyPath)
            {
                var files = Directory.GetFiles(assemblyPath, "*.dll");
    
                return files.ToList();
            }
    
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-02-27
      • 1970-01-01
      • 2012-01-31
      相关资源
      最近更新 更多