C# 使用Roslyn编译.net核心应用程序时出错
我正在生成代码,然后使用Roslyn进行编译。对于框架来说,它工作得很好,但当我尝试对核心做同样的事情时,它失败了 错误是: 程序集中类型“System.Func`2”的类型转发器 “System.Runtime”导致循环 以下是失败的代码:C# 使用Roslyn编译.net核心应用程序时出错,c#,.net-core,roslyn,C#,.net Core,Roslyn,我正在生成代码,然后使用Roslyn进行编译。对于框架来说,它工作得很好,但当我尝试对核心做同样的事情时,它失败了 错误是: 程序集中类型“System.Func`2”的类型转发器 “System.Runtime”导致循环 以下是失败的代码: using System; using System.Collections.Generic; using System.Linq; using System.Data; namespace CoreTest { public class Te
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();
}
}
}
使用系统;
使用System.Collections.Generic;
使用System.Linq;
使用系统数据;
命名空间核心测试
{
公共类TestCore
{
公开无效测试()
{
var dt=新数据表();
dt.列。添加(“A”);
变量编号=新列表();
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();
}
}
}
使用系统;
使用System.CodeDom.Compiler;
使用System.Collections.Generic;
使用System.IO;
使用System.Linq;
使用Microsoft.CodeDom.Providers.DotNetCompilerPlatform;
命名空间编译器测试
{
公共类BuildCodeCore
{
私有字符串\u CoreSassemblyFolder=@“C:\Program Files\dotnet\sdk\NuGetFallbackFolder\microsoft.netcore.app\2.1.0\ref\netcoreapp2.1”;
公共BuildCodeCore(){}
公共列表文件{get;set;}=new List();
公共字符串OutputFileName和路径{get;set;}
公共字符串ReferenceAssembliesPath{get;set;}
public void BuildCore()
{
字符串assemblyFolder=\u CoreSassemblyFolder;
字符串CoreSassemblyFileName=“System.Runtime.dll”;
var assemblies=GetAssembliesInFolder(assemblyFolder);
如果(!string.IsNullOrWhiteSpace(referenceAssembliesPath))
{
AddRange(GetAssembliesInFolder(referenceAssembliesPath));
}
CSharpCodeProvider codeProvider=新的CSharpCodeProvider();
ICodeCompiler icc=codeProvider.CreateCompiler();
CompilerParameters参数=新的CompilerParameters();
parameters.CoreSemblyFileName=CoreSemblyFileName;
parameters.referencedAssemblys.AddRange(assemblies.ToArray());
parameters.GenerateExecutable=false;
parameters.OutputAssembly=OutputFileName和Path;
CompilerResults results=icc.compileasemblyfromfilebatch(参数,Files.ToArray());
如果(results.Errors.Count>0)
{
foreach(结果中的编译器错误。错误)
{
控制台写入线(错误);
}
}
}
私有列表GetAssembliesInFolder(字符串assemblyPath)
{
var files=Directory.GetFiles(assemblyPath,*.dll);
返回files.ToList();
}
}
}
我指的是核心dll的NuGetFallbackFolder文件夹和nuget中的其他dll,System.Data.DataSetExtensions.dll
和System.Data.SqlClient.dll
都是Visual Studio中工作项目中的文件夹
如果我注释掉两个DataTable行并使用System.Data,它就会工作。
如果我把数字和项目行注释掉,它就行了
我在这里遗漏了什么?事实证明,CompileAsemblyFromFileBatch不适用于核心应用程序 我不得不切换到使用csharp编译和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();
}
}
}
使用系统;
使用System.Collections.Generic;
使用System.IO;
使用System.Linq;
使用Microsoft.CodeAnalysis;
使用Microsoft.CodeAnalysis.CSharp;
命名空间编译器测试
{
公共类BuildEmit
{
私有字符串\u CoreSassemblyFolder=@“C:\Program Files\dotnet\sdk\NuGetFallbackFolder\microsoft.netcore.app\2.1.0\ref\netcoreapp2.1”;
私有字符串\u FrameworkAssemblyFolder=@“C:\Program Files(x86)\Reference Assemblys\Microsoft\Framework\.NETFramework\v4.6.2”;
公共BuildEmit(){}
公共列表文件{get;set;}=new List();
公共字符串OutputFileName和路径{get;set;}
公共字符串ReferenceAssembliesPath{get;set;}
公共编译器类型编译器{get;set;}
公共void Build()
{
string assemblyFolder=string.Empty;
string CoreSassemblyFileName=string.Empty;
开关(编译器)
{
案例编译器类型。框架:
assemblyFolder=\u FrameworkAssemblyFolder;
CoreSassemblyFileName=“mscorlib.dll”;
打破
案例编译器类型.Core:
assemblyFolder=\u CoreSassemblyFolder;
CoreSassemblyFileName=“System.Runtime.dll”;
打破
}
PortableExecutableReference objectDef=MetadataReference.CreateFromFile(Path.Combine(assemblyFolder,CoreSassemblyFileName));
列表语法=新列表();
foreach(文件中的字符串代码文件)
{
var code=File.ReadAllText(代码文件);
var tree=CSharpSyntaxTree.ParseText(代码);
语法。添加(树);
}
var references=新列表();
添加(objectDef);
var assemblies=FilterInvalidAssembies(GetAssembliesInFolder(assemblyFolder));
如果(!string.IsNullOrWhiteSpace(referenceAssembliesPath))
{
AddRange(GetAssembliesInFolder(referenceAssembliesPath));
}
foreach(程序集中的字符串项)
{
var reference=MetadataReference.CreateFromFile(项);
参考文献。添加(参考文献);
}
var compilation=csharpcomilation.Create(Path.GetFileNameWithoutExtension(OutputFileNameAndPath)、语法、引用);
compilation=compilation.WithOptions(新的CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary));
var emitResult=compilation.Emit(OutputFileN