在CodeDomProvider(rosyln)中使用C#6function

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

当我编译我的文件时,我得到:

FileFunctions.cs(347):错误:意外字符’$’

有没有人知道如何使用CodeDom编译进行字符串插值?

我找到了这个链接: 如何使用CSharpCodeProvider定位.net 4.5?

所以我尝试过:

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

但我仍然得到同样的错误。

我还将目标框架更新为.NET Framework 4.6。

注意:我不能指定“v4.5”或“v4.6”或者我会得到:

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

我尝试过使用Thomas Levesque的建议:

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

但后来我得到:

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

我不确定为什么它试图在我的bin目录的子文件夹中查找“csc.exe”。

此路径存在:

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

但它正在寻找:

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

内置的CodeDOM提供程序不支持C#6。请使用此代码:

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

它基于Roslyn并支持C#6function。

只需改变这一行:

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

对此:

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

更新:2018年3月

请注意,NuGet版本1.0.6 … 1.0.8不会将/ roslyn文件夹复制到非Web项目的构建输出目录中。 最好坚持1.0.5 https://github.com/aspnet/RoslynCodeDomProvider/issues/38

使用C#6function的运行时编译需要一个新的编译器,如@ thomas-levesque所述。 可以使用nuget包Microsoft.CodeDom.Providers.DotNetCompilerPlatform安装此编译器。

对于桌面应用程序,存在问题。 ASP.NET团队以其无限的智慧将编译器的路径硬编码为\bin\roslyn\csc.exe请参阅https://github.com/dotnet/roslyn/issues/上的讨论9483

如果您的桌面应用程序编译为\myapp\app.exe ,则ros​​lyn编译器将位于\myapp\roslyn\csc.exeCSharpCodeProvider csc.exe CSharpCodeProvider\myapp\bin\roslyn\csc.exe

据我所知,你有两种选择

  1. 创建一个后期构建和/或安装例程,将\roslyn子目录移动到\bin\roslyn
  2. 通过reflection黑魔法修复运行时代码。

这是#2,通过将CSharpCodeProvider暴露为实用程序类中的属性。

 using System.Reflection; using Microsoft.CodeDom.Providers.DotNetCompilerPlatform; static Lazy CodeProvider { get; } = new Lazy(() => { 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; }); 

面对完全破碎的编译器的相同问题,除了Aaron的答案中列出的那些之外,还找到了第三个解决方案,通过查看我发现的库的反编译源,在设置硬编码路径{ProgramLocation}\bin\roslyn之前搜索该位置的环境变量(也是硬编码的),如果设置,则使用该变量。

考虑到这一点,像这样的一些代码也会“修复”问题:

 //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 

虽然这不会反映到内部的混乱,它仍然依赖于实现细节和滥用这样的环境变量只是感觉不对。 我个人更喜欢这个,而不是reflection选择,但同时我知道两者都依赖于确切的实现(以及硬编码路径)。

由于这个问题,以及需要调用外部程序来完成应该在进程中完成的操作,我仍然认为这个库完全被破坏了。

最近进入这个问题。 对于上下文,我试图使用System.CodeDom针对库项目运行MSTest项目,但它总是给出了一个实现C#5的编译器,无论我是否使用Microsoft.Net.CompilersMicrosoft.CodeDom.Providers.DotNetCompilerPlatform包引用由被测项目。

我对此的解决方法是:

  • 使用包Microsoft.CodeDom.Providers.DotNetCompilerPlatform
  • 将包PrivateAssets设置为contentfiles;analyzers
  • CompilerDirectoryPath 提供程序选项设置为复制的目录

PrivateAssets的默认值是contentfiles;analyzers;build ,因此获取引用项目以复制文件夹需要从设置中删除build

示例代码:

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

将此工作与Microsoft.Net.Compilers一起使用会稍微繁琐,因为没有复制,但将CompilerDirectoryPath指向包的工具文件夹的最后一步是相同的。