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
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();
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]]}
- Crear un rutina post-build y/o instalación que moverá el subdirectorio
\roslyn
a\bin\roslyn
. - 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;
});
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.
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
acontentfiles;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.
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