c# - Compiling a Syntax Tree using Roslyn -


i'm trying use roslyn generate , compile runtime library of simple objects containing get/set properties.

however, reason, compiling assembly fails error of adding linq namespace (error cs0246: type or namespace name 'system.linq' not found (are missing using directive or assembly reference?)}).

i've tried manipulating generated tree in number of ways , compiling each, still compilation fails.

the way in compilation succeeds if tree parsed string, parsed syntax tree , compiled.

the code below following:

  1. build simple syntax tree containing compilation unit, usings, namespace, class , property.
  2. try compile tree (fails)
  3. generate new syntax tree c#6 option , compile (fails)
  4. format syntax tree , compile (fails)
  5. serialize tree string, use syntaxfactory.parsesyntaxtree , compile generated tree (success)

the code:

    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 , 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 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 compile syntax tree root");          // try 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 compile new syntax tree");          // try 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 compile formatted syntax tree");           // try serialize , 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 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;         }     } 

i fell trap roslyn also. using directive not expressed string each part of qualified name syntax node. need create node this

var qualifiedname= syntaxfactory.qualifiedname(syntaxfactory.identifiername("system"),                                                      syntaxfactory.identifiername("linq"));      var usingdirective = syntaxfactory.usingdirective(qualifedname); 

i wrote helper method convert string correct syntax node.

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); } 

Comments

Popular posts from this blog

javascript - How to get current YouTube IDs via iMacros? -

c# - Maintaining a program folder in program files out of date? -

emulation - Android map show my location didn't work -