Uso de funciones de C# 6 con CodeDomProvider (rosyln)


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

CompilerParameters objCompilerParameters = new CompilerParameters();

...

CompilerResults objCompileResults = objCodeCompiler.CompileAssemblyFromFile( objCompilerParameters, files.ToArray() );

Cuando compilo mis archivos obtengo:

Funciones de archivo.cs (347): Error: Carácter inesperado ' {'

¿Alguien sabe cómo hacer que la interpolación de cadenas funcione con la compilación de CodeDom?

Encontré este enlace: ¿Cómo apuntar a. net 4.5 con CSharpCodeProvider?

Así que lo intenté:

     var providerOptions = new Dictionary<string, string>();
     providerOptions.Add( "CompilerVersion", "v4.0" );

     // Instantiate the compiler.
     CodeDomProvider objCodeCompiler = CodeDomProvider.CreateProvider( "CSharp", providerOptions );

Pero sigo teniendo el mismo error.

También actualizé el framework target a.NET Framework 4.6.

NOTA: No puedo especificar "v4. 5" o "v4. 6"o obtendré:

************** 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)

He intentado usar la sugerencia de Thomas Levesque:

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

Pero entonces obtengo:

************** 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)

No estoy seguro de por qué está tratando de buscar "csc.exe " en una subcarpeta de mi directorio bin.

Este camino existe:

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

Pero estaba buscando:

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

Author: Community, 2015-07-26

4 answers

El proveedor de código incorporado no soporta C# 6. Use este en su lugar:

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

Está basado en Roslyn y soporta las características de C# 6.

Simplemente cambia esta línea:

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

A esto:

CodeDomProvider objCodeCompiler = new Microsoft.CodeDom.Providers.DotNetCompilerPlatform.CSharpCodeProvider();
 18
Author: Thomas Levesque,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-07-26 20:26:34

Actualización: Marzo de 2018

Palabra de precaución, NuGet versión 1.0.6 ... 1.0.8 se no copiar la carpeta / roslyn al directorio de salida de compilación en sitios no web proyecto. Mejor palo con 1.0.5 https://github.com/aspnet/RoslynCodeDomProvider/issues/38

La compilación en tiempo de ejecución usando características de C#6 requiere un nuevo compilador, como @thomas-levesque mencionó. Este compilador se puede instalar usando el paquete nuget Microsoft.CodeDom.Providers.DotNetCompilerPlatform.

Para las aplicaciones de escritorio, hay un problema. Las ASP.NET equipo, en su infinita sabiduría han codificado el camino al compilador como <runtime-directory>\bin\roslyn\csc.exe Ver discusión en https://github.com/dotnet/roslyn/issues/9483

Si su aplicación de escritorio está compilada en \myapp\app.exe, el compilador de roslyn se ubicará en \myapp\roslyn\csc.exe, PERO EL {[5] } RESOLVERÁ csc.exe como \myapp\bin\roslyn\csc.exe

Por lo que puedo decir, tienes dos opciones{[15]]}

  1. Crear un rutina post-build y/o instalación que moverá el subdirectorio \roslyn a \bin\roslyn.
  2. Corrige el código de tiempo de ejecución a través de la magia negra de reflexión.

Aquí está #2, exponiendo el CSharpCodeProvider como una propiedad en una clase de utilidad.

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;
});
 22
Author: Aaron Hudon,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-03-16 19:51:26

Se enfrentó al mismo problema del compilador completamente roto y encontré una tercera solución además de las enumeradas en la respuesta de Aaron's, al mirar la fuente descompilada de la biblioteca encontré que, antes de establecer la ruta codificada {ProgramLocation}\bin\roslyn busca una variable de entorno (también codificada) para esa ubicación, y si se establece, la usa en su lugar.

Con eso en mente, algún código como este también "arreglaría" el problema:

//Set hardcoded environment variable to set the path to the library
Environment.SetEnvironmentVariable("ROSLYN_COMPILER_LOCATION", "actual compiler location goes here", EnvironmentVariableTarget.Process);
//Create compiler object
CSharpCodeProvider compiler = new CSharpCodeProvider();
//Clean up
Environment.SetEnvironmentVariable("ROSLYN_COMPILER_LOCATION", null, EnvironmentVariableTarget.Process);

//Use "compiler" variable to actually compile the dynamic code

Mientras que esto no recurre a reflexión para meterse con los aspectos internos, todavía se basa en los detalles de la implementación y abusar de las variables de entorno como este simplemente se siente mal. Personalmente me gusta esto más que la alternativa de reflexión, pero al mismo tiempo sé que ambas dependen de la implementación exacta (así como de la ruta codificada).

Debido a este problema, y la necesidad de llamar a un programa externo para hacer lo que se debe hacer en el proceso, todavía considero que esta biblioteca está completamente rota.

 0
Author: Alejandro,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-03-23 15:31:40

Se topó con este tema recientemente. Para el contexto, estaba tratando de ejecutar un proyecto MSTest contra un proyecto de biblioteca usando System.CodeDom, pero siempre daba un compilador que implementaba C# 5 si tenía o no paquetes Microsoft.Net.Compilers o Microsoft.CodeDom.Providers.DotNetCompilerPlatform referenciados por el proyecto bajo prueba.

Mi solución para esto fue:

  • Use el paquete Microsoft.CodeDom.Providers.DotNetCompilerPlatform
  • Establecer el paquete PrivateAssets a contentfiles;analyzers
  • Pase opciones de proveedor con CompilerDirectoryPath establecido en el directorio copiado

El predeterminado el valor para PrivateAssets es contentfiles;analyzers;build, por lo que para que los proyectos de referencia también copien la carpeta es necesario eliminar build de la configuración.

Código de ejemplo:

var compiler = CodeDomProvider.CreateProvider("cs", new Dictionary<string, string> {
    { "CompilerDirectoryPath", Path.Combine(Environment.CurrentDirectory, "roslyn") }
});

Hacer que esto funcione con Microsoft.Net.Compilers sería un poco más tedioso ya que no se hace ninguna copia, pero el paso final de apuntar CompilerDirectoryPath a la carpeta herramientas del paquete es el mismo.

 0
Author: tychon,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-09-29 22:41:45