CoreLib问题
最近学习Roslyn,看如何编译一个Dll来使用,网上有很多Roslyn的文章,但是都有点问题,我编译的DLL加入到别的项目使用,就会提示:
严重性 代码 说明 项目 文件 行 禁止显示状态
错误 CS0012 类型“Object”在未引用的程序集中定义。必须添加对程序集“System.Private.CoreLib, Version=7.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e”的引用。 ConsoleApp1 G:\Github\MMCServer\MMCEngine\ConsoleApp1\Program.cs 14 活动
先放上代码来:
动态脚本:
using System;
public class MyLib
{
public static string GetGreeting()
{
return "Ahoy";
}
}
生成脚本:
public void writedll()
{
string sourceCode = File.ReadAllText(@"c:\Temp\MyLib.cs");
SyntaxTree syntaxTree = SyntaxFactory.ParseSyntaxTree(SourceText.From(sourceCode));
var assemblyPath = Path.GetDirectoryName(typeof(object).Assembly.Location);
Console.Write("dll path :"+ assemblyPath);
List<MetadataReference> list = new List<MetadataReference>()
{
MetadataReference.CreateFromFile(typeof(object).Assembly.Location),
MetadataReference.CreateFromFile(typeof(SyntaxTree).Assembly.Location),
MetadataReference.CreateFromFile(typeof(CSharpSyntaxTree).Assembly.Location)
};
CSharpCompilation compilation = CSharpCompilation
.Create("MyLib")
.WithOptions(new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary))
.AddReferences(list)
.AddSyntaxTrees(syntaxTree);
EmitResult result = compilation.Emit(@"c:\Temp\MyLib.dll");
if (!result.Success)
Console.Out.WriteLine(string.Join(Environment.NewLine, result.Diagnostics.Select(diagnostic => diagnostic.ToString())));
}
我们运行这个函数后就生成了DLL。
在控制台里运行
然后我们创建一个控制台项目来使用这个MyLib.dll
代码只有短短的两行
Console.WriteLine("Hello, World!");
Console.WriteLine(MyLib.GetGreeting());
如下图,已经报告出了错误。
错误 CS0012 类型“Object”在未引用的程序集中定义。必须添加对程序集“System.Private.CoreLib, Version=7.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e”的引用。
在网络找了很多资料一直,大概是DLL编译引用了错误的元数据引用(MetadataReference),应该引用“引用程序集(reference assemblies)”不应该引用“实现程序集(implementation assemblies)”。
那我们只改掉代码,路径里是我的,不同机器和版本可能位置不同,自行修改。
修改后
public void writedll()
{
string sourceCode = File.ReadAllText(@"c:\Temp\MyLib.cs");
SyntaxTree syntaxTree = SyntaxFactory.ParseSyntaxTree(SourceText.From(sourceCode));
var assemblyPath = Path.GetDirectoryName(typeof(object).Assembly.Location);
Console.Write("dll path :"+ assemblyPath);
List<MetadataReference> list = new List<MetadataReference>()
{
//MetadataReference.CreateFromFile(typeof(object).Assembly.Location),
//MetadataReference.CreateFromFile(typeof(SyntaxTree).Assembly.Location),
//MetadataReference.CreateFromFile(typeof(CSharpSyntaxTree).Assembly.Location)
};
string dllpath = @"C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\7.0.9\ref\net7.0\";
foreach (string dll in Directory.GetFiles(dllpath, "*.dll"))
{
if (!dll.Contains("VisualBasic"))
list.Add(MetadataReference.CreateFromFile(dll));
}
CSharpCompilation compilation = CSharpCompilation
.Create("MyLib")
.WithOptions(new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary))
.AddReferences(list)
.AddSyntaxTrees(syntaxTree);
EmitResult result = compilation.Emit(@"c:\Temp\MyLib.dll");
if (!result.Success)
Console.Out.WriteLine(string.Join(Environment.NewLine, result.Diagnostics.Select(diagnostic => diagnostic.ToString())));
}
运行后,重新生成了DLL,这样就可以直接运行没有报错了。
最后
当然这里的引用程序集比较粗暴,这里不再探讨。
这个问题让我卡了很久,遇到同样的问题的可以参考借鉴吧。
因为学习中,可能存在错误,还请留言。
#参考
https://github.com/dotnet/core/issues/2082
https://stackoverflow.com/questions/68109143/choose-references-dynamically-in-net-core-for-roslyn