Utilisation des fonctionnalités C# 6 avec CodeDomProvider (rosyln)
CodeDomProvider objCodeCompiler = CodeDomProvider.CreateProvider( "CSharp" );
CompilerParameters objCompilerParameters = new CompilerParameters();
...
CompilerResults objCompileResults = objCodeCompiler.CompileAssemblyFromFile( objCompilerParameters, files.ToArray() );
quand je compile mes fichiers j'obtiens:
FileFunctions.cs (347): erreur: caractère inattendu '$'
est-ce que quelqu'un sait comment obtenir l'interpolation de chaîne de travail avec la compilation CodeDom?
j'ai trouvé ce lien: comment cibler .net 4.5 avec CSharpCodeProvider?
donc j'ai essayé:
var providerOptions = new Dictionary<string, string>();
providerOptions.Add( "CompilerVersion", "v4.0" );
// Instantiate the compiler.
CodeDomProvider objCodeCompiler = CodeDomProvider.CreateProvider( "CSharp", providerOptions );
mais je continue obtenir la même erreur.
j'ai également mis à jour le cadre cible en .net cadre 4.6.
NOTE: je ne peux pas spécifier "v4.5" ou "v4.6" ou je vais obtenir:
************** 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:UsersDerek.MorinDocumentsVisual Studio 2010ProjectsScriptCodeScriptCode.ConvertedToC#CoreCodeDOMCompiler.cs:line 93
at NewForm.InitializeSystem() in C:UsersDerek.MorinDocumentsVisual Studio 2010ProjectsScriptCodeScriptCode.ConvertedToC#NewForm.cs:line 179
at NewForm.NewForm_Load(Object sender, EventArgs e) in C:UsersDerek.MorinDocumentsVisual Studio 2010ProjectsScriptCodeScriptCode.ConvertedToC#NewForm.cs:line 111
at System.Windows.Forms.Form.OnLoad(EventArgs e)
j'ai essayé d'utiliser la suggestion de Thomas Levesque:
CodeDomProvider objCodeCompiler = new Microsoft.CodeDom.Providers.DotNetCompilerPlatform.CSharpCodeProvider();
mais alors je reçois:
************** Exception Text **************
System.IO.DirectoryNotFoundException: Could not find a part of the path 'C:UsersDerek.MorinDocumentsVisual Studio 2010ProjectsScriptCodeScriptCode.ConvertedToC#binx86Debugbinroslyncsc.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:UsersDerek.MorinDocumentsVisual Studio 2010ProjectsScriptCodeScriptCode.ConvertedToC#CoreCodeDOMCompiler.cs:line 87
at NewForm.InitializeSystem() in C:UsersDerek.MorinDocumentsVisual Studio 2010ProjectsScriptCodeScriptCode.ConvertedToC#NewForm.cs:line 179
at NewForm.NewForm_Load(Object sender, EventArgs e) in C:UsersDerek.MorinDocumentsVisual Studio 2010ProjectsScriptCodeScriptCode.ConvertedToC#NewForm.cs:line 111
at System.Windows.Forms.Form.OnLoad(EventArgs e)
Je ne sais pas pourquoi il cherche" csc.exe" dans un sous-dossier de mon répertoire bin.
Ce chemin existe:
C:UsersDerek.MorinDocumentsVisual Studio 2010ProjectsScriptCodeScriptCode.ConvertedToC#binx86Debugroslyn
mais il cherchait:
C:UsersDerek.MorinDocumentsVisual Studio 2010ProjectsScriptCodeScriptCode.ConvertedToC#binx86Debugbinroslyncsc.exe
4 réponses
le fournisseur de code intégré ne supporte pas C# 6. Utilisez plutôt celle-ci:
https://www.nuget.org/packages/Microsoft.CodeDom.Providers.DotNetCompilerPlatform /
est basé sur Roslyn et supporte les fonctionnalités C# 6.
il suffit de changer cette ligne:
CodeDomProvider objCodeCompiler = CodeDomProvider.CreateProvider( "CSharp" );
à ceci:
CodeDomProvider objCodeCompiler = new Microsoft.CodeDom.Providers.DotNetCompilerPlatform.CSharpCodeProvider();
La compilationMise À Jour: Mars 2018
mise en garde, NuGet Version 1.0.6 ... 1.0.8 va ne pas copier le dossier / roslyn dans le répertoire de sortie de build sur non-web projet. Meilleur bâton avec 1.0.5 https://github.com/aspnet/RoslynCodeDomProvider/issues/38
avec les fonctionnalités C#6 nécessite un nouveau compilateur, comme @thomas-levesque l'a mentionné. Ce compilateur peut être installé en utilisant le paquet nuget Microsoft.CodeDom.Providers.DotNetCompilerPlatform
.
pour les applications bureautiques, il y a un problème. Les ASP.NET équipe, dans leur sagesse infinie ont codé dur le chemin vers le compilateur comme <runtime-directory>\bin\roslyn\csc.exe
voir la discussion à https://github.com/dotnet/roslyn/issues/9483
si votre application de bureau est compilée en \myapp\app.exe
, le compilateur roslyn sera situé à \myapp\roslyn\csc.exe
, mais le CSharpCodeProvider
résoudra csc.exe
comme \myapp\bin\roslyn\csc.exe
autant que je sache, vous avez deux options
- créez une routine de post-construction et/ou d'installation qui déplacera le sous-répertoire
\roslyn
à\bin\roslyn
. - fixez le code runtime par magie noire de réflexion.
voici #2, en exposant le CSharpCodeProvider
en tant que propriété dans une classe utilitaire.
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;
});
fait face à la même question du compilateur complètement cassé et a trouvé une troisième solution en plus de ceux énumérés dans la réponse D'Aaron , en regardant la source décomposée de la bibliothèque, j'ai trouvé que, avant de définir le chemin hardcodé {ProgramLocation}\bin\roslyn
il recherche une variable d'environnement (aussi hardcodé) pour cet endroit, et si elle est définie, il utilise à la place.
avec cela à l'esprit, un code comme celui - ci pourrait aussi" corriger " le problème:
//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
bien que cela n'ait pas recours à la réflexion pour brouiller les internes, cela repose toujours sur des détails d'implémentation et abuser de variables d'environnement comme cela semble tout simplement mal. J'aime personnellement cela plus que l'alternative de réflexion, mais en même temps je sais que les deux repose sur la mise en œuvre exacte (ainsi que le chemin codé).
en Raison de ce problème, et la nécessité d'appeler un programme externe pour faire ce qui devrait être fait en cours de route, je considère toujours cette bibliothèque comme complètement cassée.
a rencontré ce problème récemment. Pour le contexte, j'essayais d'exécuter un projet MSTest contre un projet de bibliothèque en utilisant System.CodeDom
, mais il donnait toujours un compilateur qui implémentait C# 5 que j'aie ou non des paquets Microsoft.Net.Compilers
ou Microsoft.CodeDom.Providers.DotNetCompilerPlatform
référencés par le projet à l'essai.
ma solution pour cela était:
- utiliser le paquet
Microsoft.CodeDom.Providers.DotNetCompilerPlatform
- Ensemble
PrivateAssets
àcontentfiles;analyzers
- Pass options de fournisseur avec
CompilerDirectoryPath
ensemble pour le répertoire copié
la valeur par défaut pour PrivateAssets
est contentfiles;analyzers;build
, donc obtenir des projets de référencement pour copier aussi le dossier nécessite de supprimer build
du paramètre.
exemple de code:
var compiler = CodeDomProvider.CreateProvider("cs", new Dictionary<string, string> {
{ "CompilerDirectoryPath", Path.Combine(Environment.CurrentDirectory, "roslyn") }
});
faire fonctionner ça avec Microsoft.Net.Compilers
serait un peu plus fastidieux comme aucune copie n'est faite, mais l'étape finale de pointage CompilerDirectoryPath
vers le dossier Outils Du paquet est la même.