gpt4 book ai didi

c# - Roslyn 内存编译 : CS0103: The name 'Console' does not exist in the current context

转载 作者:太空狗 更新时间:2023-10-30 01:13:13 28 4
gpt4 key购买 nike

所以我遇到了这个问题。

我正在尝试在内存中编译代码并通过搜索语法树添加 namespace 引用,因此我不会手动添加它们。尝试模拟 Visual Studio 可能如何做到这一点。

我在编译部门有点头疼。即使我在读取语法树时添加了对系统的元数据引用,它也找不到 System.Console。

关键是我希望它自己包含程序集,我不想添加“MetadataReference.CreateFromFile(....,”System.Console”)。

我解释了下面的代码,以便清楚发生了什么。

class App
{
static void Main(string[] args)
{
//creating the syntax tree for the program
SyntaxTree syntaxTree = CSharpSyntaxTree.ParseText(@"
namespace ns{
using System;
public class App{
public static void Main(string[] args){
Console.Write(""dada"");
}
}


}");
//creating options that tell the compiler to output a console application
var options = new CSharpCompilationOptions(
OutputKind.ConsoleApplication,
optimizationLevel: OptimizationLevel.Debug,
allowUnsafe: true);

//creating the compilation
var compilation = CSharpCompilation.Create(Path.GetRandomFileName(), options: options);

//adding the syntax tree
compilation = compilation.AddSyntaxTrees(syntaxTree);

//getting the local path of the assemblies
var assemblyPath = Path.GetDirectoryName(typeof(object).Assembly.Location);
List<MetadataReference> references = new List<MetadataReference>();
//adding the core dll containing object and other classes
references.Add(MetadataReference.CreateFromFile(Path.Combine(assemblyPath, "System.Private.CoreLib.dll")));
references.Add(MetadataReference.CreateFromFile(Path.Combine(assemblyPath, "mscorlib.dll")));
//gathering all using directives in the compilation
var usings = compilation.SyntaxTrees.Select(tree => tree.GetRoot().ChildNodes().OfType<UsingDirectiveSyntax>()).SelectMany(s => s).ToArray();

//for each using directive add a metadatareference to it
foreach (var u in usings)
{
references.Add(MetadataReference.CreateFromFile(Path.Combine(assemblyPath, u.Name.ToString() + ".dll")));
}

//add the reference list to the compilation
compilation=compilation.AddReferences(references);

//compile
using (var ms = new MemoryStream())
{
EmitResult result = compilation.Emit(ms);

if (!result.Success)
{
IEnumerable<Diagnostic> failures = result.Diagnostics.Where(diagnostic =>
diagnostic.IsWarningAsError ||
diagnostic.Severity == DiagnosticSeverity.Error);

foreach (Diagnostic diagnostic in failures)
{
Console.Error.WriteLine("{0}: {1}, {2}", diagnostic.Id, diagnostic.GetMessage(), diagnostic.Location);
}
}
else
{
ms.Seek(0, SeekOrigin.Begin);
AssemblyLoadContext context = AssemblyLoadContext.Default;
Assembly assembly = context.LoadFromStream(ms);
assembly.EntryPoint.Invoke(null, new object[] { new string[] { "arg1", "arg2", "etc" } });

}
}
}
}

最佳答案

  • 在 .net 核心中 System.Console 位于 System.Console.dll 中。所以你需要在上面添加引用
  • 您需要在 System.Runtime.dll 上添加引用以正确解析预定义类型:objectbool 等等
  • SyntaxNode.ChildNodes() 只返回 child ,这意味着它不返回后代节点,所以如果你想获得所有 UsingDirectiveSyntax 你应该改变你的逻辑.作为一种方法,只需使用 SyntaxNode.DescendantNodes()

应用所有建议后,您会得到类似这样的结果(未更改的部分将被跳过):

  ...
//adding the core dll containing object and other classes
references.Add(MetadataReference.CreateFromFile(Path.Combine(assemblyPath, "System.Private.CoreLib.dll")));
references.Add(MetadataReference.CreateFromFile(Path.Combine(assemblyPath, "System.Console.dll")));
references.Add(MetadataReference.CreateFromFile(Path.Combine(assemblyPath, "System.Runtime.dll")));

//gathering all using directives in the compilation
var usings = compilation.SyntaxTrees.Select(tree => tree.GetRoot().DescendantNodes().OfType<UsingDirectiveSyntax>()).SelectMany(s => s).ToArray();
...

关于c# - Roslyn 内存编译 : CS0103: The name 'Console' does not exist in the current context,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50879342/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com