Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using C# 6 features with CodeDomProvider (Roslyn)

CodeDomProvider objCodeCompiler = CodeDomProvider.CreateProvider( "CSharp" );  CompilerParameters objCompilerParameters = new CompilerParameters();  ...  CompilerResults objCompileResults = objCodeCompiler.CompileAssemblyFromFile( objCompilerParameters, files.ToArray() ); 

When I compile my files I get:

FileFunctions.cs(347): Error: Unexpected character '$'

Does anyone know how to get string interpolation working with CodeDom compiling?

I found this link: How to target .net 4.5 with CSharpCodeProvider?

So I tried:

     var providerOptions = new Dictionary<string, string>();      providerOptions.Add( "CompilerVersion", "v4.0" );       // Instantiate the compiler.      CodeDomProvider objCodeCompiler = CodeDomProvider.CreateProvider( "CSharp", providerOptions ); 

But I still get the same error.

I also updated the target framework to .NET Framework 4.6.

NOTE: I can't specify "v4.5" or "v4.6" or I will get:

************** Exception Text ************** System.InvalidOperationException: Compiler executable file csc.exe cannot be found.    at System.CodeDom.Compiler.RedistVersionInfo.GetCompilerPath(IDictionary`2 provOptions, String compilerExecutable)    at Microsoft.CSharp.CSharpCodeGenerator.FromFileBatch(CompilerParameters options, String[] fileNames)    at Microsoft.CSharp.CSharpCodeGenerator.System.CodeDom.Compiler.ICodeCompiler.CompileAssemblyFromFileBatch(CompilerParameters options, String[] fileNames)    at System.CodeDom.Compiler.CodeDomProvider.CompileAssemblyFromFile(CompilerParameters options, String[] fileNames)    at Dynamic.CodeDOMCompiler.CompileAllCodeFiles() in C:\Users\Derek.Morin\Documents\Visual Studio 2010\Projects\ScriptCode\ScriptCode.ConvertedToC#\Core\CodeDOMCompiler.cs:line 93    at NewForm.InitializeSystem() in C:\Users\Derek.Morin\Documents\Visual Studio 2010\Projects\ScriptCode\ScriptCode.ConvertedToC#\NewForm.cs:line 179    at NewForm.NewForm_Load(Object sender, EventArgs e) in C:\Users\Derek.Morin\Documents\Visual Studio 2010\Projects\ScriptCode\ScriptCode.ConvertedToC#\NewForm.cs:line 111    at System.Windows.Forms.Form.OnLoad(EventArgs e) 

I have tried using the suggestion by Thomas Levesque:

CodeDomProvider objCodeCompiler = new Microsoft.CodeDom.Providers.DotNetCompilerPlatform.CSharpCodeProvider(); 

But then I get:

************** Exception Text ************** System.IO.DirectoryNotFoundException: Could not find a part of the path 'C:\Users\Derek.Morin\Documents\Visual Studio 2010\Projects\ScriptCode\ScriptCode.ConvertedToC#\bin\x86\Debug\bin\roslyn\csc.exe'.    at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)    at System.IO.FileStream.Init(String path, FileMode mode, FileAccess access, Int32 rights, Boolean useRights, FileShare share, Int32 bufferSize, FileOptions options, SECURITY_ATTRIBUTES secAttrs, String msgPath, Boolean bFromProxy, Boolean useLongPath, Boolean checkHost)    at System.IO.FileStream..ctor(String path, FileMode mode, FileAccess access, FileShare share)    at Microsoft.CodeDom.Providers.DotNetCompilerPlatform.Compiler.get_CompilerName()    at Microsoft.CodeDom.Providers.DotNetCompilerPlatform.Compiler.FromFileBatch(CompilerParameters options, String[] fileNames)    at Microsoft.CodeDom.Providers.DotNetCompilerPlatform.Compiler.CompileAssemblyFromFileBatch(CompilerParameters options, String[] fileNames)    at System.CodeDom.Compiler.CodeDomProvider.CompileAssemblyFromFile(CompilerParameters options, String[] fileNames)    at Dynamic.CodeDOMCompiler.CompileAllCodeFiles() in C:\Users\Derek.Morin\Documents\Visual Studio 2010\Projects\ScriptCode\ScriptCode.ConvertedToC#\Core\CodeDOMCompiler.cs:line 87    at NewForm.InitializeSystem() in C:\Users\Derek.Morin\Documents\Visual Studio 2010\Projects\ScriptCode\ScriptCode.ConvertedToC#\NewForm.cs:line 179    at NewForm.NewForm_Load(Object sender, EventArgs e) in C:\Users\Derek.Morin\Documents\Visual Studio 2010\Projects\ScriptCode\ScriptCode.ConvertedToC#\NewForm.cs:line 111    at System.Windows.Forms.Form.OnLoad(EventArgs e) 

I'm not sure why it is trying to look for "csc.exe" in a subfolder of my bin directory.

This path exists:

C:\Users\Derek.Morin\Documents\Visual Studio 2010\Projects\ScriptCode\ScriptCode.ConvertedToC#\bin\x86\Debug\roslyn

But it was looking for:

C:\Users\Derek.Morin\Documents\Visual Studio 2010\Projects\ScriptCode\ScriptCode.ConvertedToC#\bin\x86\Debug\bin\roslyn\csc.exe

like image 262
Derek Avatar asked Jul 26 '15 17:07

Derek


People also ask

What is using () in C#?

The using statement causes the object itself to go out of scope as soon as Dispose is called. Within the using block, the object is read-only and can't be modified or reassigned. A variable declared with a using declaration is read-only.

How do I start learning C?

Get started with C. Official C documentation - Might be hard to follow and understand for beginners. Visit official C Programming documentation. Write a lot of C programming code - The only way you can learn programming is by writing a lot of code.

Is C hard to learn?

While C is one of the more difficult languages to learn, it's still an excellent first language pick up because almost all programming languages are implemented in it. This means that once you learn C, it'll be simple to learn more languages like C++ and C#.


2 Answers

Update: March 2018

Word of caution, NuGet version 1.0.6 ... 1.0.8 will not copy the /roslyn folder to the build output directory on non-web projects. Best stick with 1.0.5 https://github.com/aspnet/RoslynCodeDomProvider/issues/38

Run-time compilation using C#6 features requires a new compiler, as @thomas-levesque mentioned. This compiler can be installed by using the nuget package Microsoft.CodeDom.Providers.DotNetCompilerPlatform.

For desktop applications, there's a problem. The ASP.NET team, in their infinite wisdom have hard-coded the path to the compiler as <runtime-directory>\bin\roslyn\csc.exe See discussion at https://github.com/dotnet/roslyn/issues/9483

If your desktop application is compiled to \myapp\app.exe, the roslyn compiler will be located at \myapp\roslyn\csc.exe, BUT THE CSharpCodeProvider WILL RESOLVE csc.exe as \myapp\bin\roslyn\csc.exe

As far as I can tell, you have two options

  1. Create a post-build and/or installation routine that will move the \roslyn subdirectory to \bin\roslyn.
  2. Fix the runtime code through reflection black magic.

Here is #2, by exposing the CSharpCodeProvider as a property in a utility class.

using System.Reflection; using Microsoft.CodeDom.Providers.DotNetCompilerPlatform;  static Lazy<CSharpCodeProvider> CodeProvider { get; } = new Lazy<CSharpCodeProvider>(() => {     var csc = new CSharpCodeProvider();     var settings = csc         .GetType()         .GetField("_compilerSettings", BindingFlags.Instance | BindingFlags.NonPublic)         .GetValue(csc);      var path = settings         .GetType()         .GetField("_compilerFullPath", BindingFlags.Instance | BindingFlags.NonPublic);      path.SetValue(settings, ((string)path.GetValue(settings)).Replace(@"bin\roslyn\", @"roslyn\"));      return csc; }); 
like image 146
Aaron Hudon Avatar answered Oct 02 '22 10:10

Aaron Hudon


The built-in CodeDOM provider doesn't support C# 6. Use this one instead:

https://www.nuget.org/packages/Microsoft.CodeDom.Providers.DotNetCompilerPlatform/

It's based on Roslyn and supports the C# 6 features.

Just change this line:

CodeDomProvider objCodeCompiler = CodeDomProvider.CreateProvider( "CSharp" ); 

to this:

CodeDomProvider objCodeCompiler = new Microsoft.CodeDom.Providers.DotNetCompilerPlatform.CSharpCodeProvider(); 
like image 22
Thomas Levesque Avatar answered Oct 02 '22 12:10

Thomas Levesque