Rob*_*Rob 4 c# roslyn .net-core
所以我遇到了这个问题。
我正在尝试在内存中编译代码并通过搜索语法树添加命名空间引用,因此我不会手动添加它们。试图模拟 Visual Studio 可能是如何做到的。
我在编译部门有点不知所措。即使我在阅读语法树时添加对 System 的元数据引用,它也找不到 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" } });
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
System.Console存在于System.Console.dll. 所以你需要在它上面添加引用System.Runtime.dll以正确解析预定义类型:object,bool等等SyntaxNode.ChildNodes()只返回孩子,这意味着它不返回后代节点,所以如果你想得到所有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();
...
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1064 次 |
| 最近记录: |