但是,由于某种原因,编译程序集失败,添加Linq名称空间时出错(错误CS0246:找不到类型或名称空间名称’System.linq'(您是否缺少using指令或程序集引用?)}) .
我曾尝试以多种方式 *** 作生成的树并编译每个,但仍然编译失败.
编译成功的唯一方法是将树解析为字符串,然后解析回语法树然后编译.
以下代码执行以下 *** 作:
>构建一个包含编译单元,使用,命名空间,类和属性的简单语法树.
>尝试编译树(失败)
>使用C#6选项生成新的语法树并编译(失败)
>格式化语法树并编译(失败)
>将树序列化为字符串,然后使用SyntaxFactory.ParseSyntaxTree并编译生成的树(成功)
代码:
private static Readonly CSharpCompilationoptions DefaultCompilationoptions = new CSharpCompilationoptions(OutputKind.Dynamicallylinkedlibrary) .WithOverflowChecks(true) .WithPlatform(Platform.X86) .WithOptimizationLevel(OptimizationLevel.Release) .WithUsings(Defaultnamespaces); private static Readonly IEnumerable<string> Defaultnamespaces = new[] { "System","System.IO","System.Net","System.linq","System.Text","System.Text.RegularExpressions" }; private static Readonly IEnumerable<MetadataReference> DefaultReferences = new[] { MetadataReference.CreateFromfile(typeof (object).Assembly.Location),MetadataReference.CreateFromfile(typeof (System.linq.Enumerable).Assembly.Location),MetadataReference.CreateFromfile(typeof (System.GenericUriParser).Assembly.Location),MetadataReference.CreateFromfile(typeof (Microsoft.CSharp.RuntimeBinder.RuntimeBinderException).Assembly.Location) }; static voID Main(string[] args) { MakeAssembly(); Console.Readline(); } private static voID MakeAssembly() { //Compilation Unit and Usings compilationunitSyntax cu = SyntaxFactory.compilationunit() .AddUsings(SyntaxFactory.UsingDirective(SyntaxFactory.IDentifIErname("System")),SyntaxFactory.UsingDirective(SyntaxFactory.IDentifIErname(typeof(System.linq.Enumerable).namespace))) ; // nameSpace namespaceDeclarationSyntax ns = SyntaxFactory.namespaceDeclaration(SyntaxFactory.IDentifIErname("Roslyn")); // Class ClassDeclarationSyntax classNode = SyntaxFactory.ClassDeclaration("MyClass") .AddModifIErs(SyntaxFactory.Token(SyntaxKind.PublicKeyword)) ; // Property classNode= classNode.AddMembers( SyntaxFactory.PropertyDeclaration(SyntaxFactory.ParseTypename("Int32"),"MyProperty") .AddAccessorListAccessors( SyntaxFactory.AccessorDeclaration(SyntaxKind.GetAccessorDeclaration).WithSemicolonToken(SyntaxFactory.Token(SyntaxKind.SemicolonToken)),SyntaxFactory.AccessorDeclaration(SyntaxKind.SetAccessorDeclaration).WithSemicolonToken(SyntaxFactory.Token(SyntaxKind.SemicolonToken))). AddModifIErs(SyntaxFactory.Token(SyntaxKind.PublicKeyword))); ns = ns.AddMembers(classNode); cu = cu.AddMembers(ns); // Try To Compile Syntax Tree root var root = cu.SyntaxTree.GetRoot(); var st = root.SyntaxTree; var assembly = CompileAndLoad(st); if (assembly != null) { Console.Writeline("Success compile Syntax tree root"); return; } else Console.Writeline("Failed to compile Syntax tree root"); // Try to compile new Syntax tree var stNew = SyntaxFactory.SyntaxTree(cu,CSharpParSEOptions.Default.WithLanguageVersion(LanguageVersion.CSharp6)); assembly = CompileAndLoad(stNew); if (assembly != null) { Console.Writeline("Success compile new Syntax tree"); return; } else Console.Writeline("Failed to compile new Syntax tree"); // Try to format node AdhocWorkspace cw = new AdhocWorkspace(); OptionSet options = cw.Options; options = options.WithChangedOption(CSharpformattingOptions.NewlinesForBracesInMethods,false); options = options.WithChangedOption(CSharpformattingOptions.NewlinesForBracesInTypes,false); SyntaxNode formattednode = Formatter.Format(cu,cw,options); var stFormat = SyntaxFactory.SyntaxTree(cu,CSharpParSEOptions.Default.WithLanguageVersion(LanguageVersion.CSharp6)); assembly = CompileAndLoad(stFormat); if (assembly != null) { Console.Writeline("Success compile formatted Syntax tree"); return; } else Console.Writeline("Failed to compile formatted Syntax tree"); // Try to serialize and parse StringBuilder sb = new StringBuilder(); using (StringWriter writer = new StringWriter(sb)) { formattednode.Writeto(writer); } var treeAsstring = sb.ToString(); var stParsed = SyntaxFactory.ParseSyntaxTree(treeAsstring); assembly = CompileAndLoad(stParsed); if (assembly != null) { Console.Writeline("Success compile parsed Syntax tree"); return; } else Console.Writeline("Failed to compile formatted Syntax tree"); } private static Assembly CompileAndLoad(SyntaxTree st) { var compilation = CSharpCompilation.Create("TestRoslyn.dll",new SyntaxTree[] { st },null,DefaultCompilationoptions); compilation = compilation.Withreferences(DefaultReferences); using (var stream = new MemoryStream()) { EmitResult result = compilation.Emit(stream); if (result.Success) { var assembly = Assembly.Load(stream.GetBuffer()); return assembly; } return null; } }解决方法 罗斯林也陷入了这个陷阱. using指令不仅表示为字符串,限定名称的每个部分都是语法节点.您需要像这样创建节点
var qualifIEdname= SyntaxFactory.QualifIEdname(SyntaxFactory.IDentifIErname("System"),SyntaxFactory.IDentifIErname("linq")); var usingDirective = SyntaxFactory.UsingDirective(qualifedname);
我编写了一个帮助方法来将字符串转换为正确的语法节点.
private UsingDirectiveSyntax CreateUsingDirective(string usingname){ nameSyntax qualifIEdname = null; foreach (var IDentifIEr in usingname.Split('.')) { var name = SyntaxFactory.IDentifIErname(IDentifIEr); if (qualifIEdname != null) { qualifIEdname = SyntaxFactory.QualifIEdname(qualifIEdname,name); } else { qualifIEdname = name; } } return SyntaxFactory.UsingDirective(qualifIEdname);}总结
以上是内存溢出为你收集整理的c# – 使用Roslyn编译语法树全部内容,希望文章能够帮你解决c# – 使用Roslyn编译语法树所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)