在.Net Core 1.0中运行时编译和运行代码

是否可以在新的.Net Core(更好的.Net标准平台)中运行时编译和运行c#代码? 我见过一些例子(.Net Framework),但是使用过的NuGet包

与netcoreapp1.0不兼容(.NETCoreApp,Version = v1.0)

选项#1 :使用完整的C#编译器编译程序集,加载它然后从中执行一个方法。

这需要以下包作为project.json中的依赖项:

"Microsoft.CodeAnalysis.CSharp": "1.3.0-beta1-20160429-01", "System.Runtime.Loader": "4.0.0-rc2-24027", 

然后你可以使用这样的代码:

 var compilation = CSharpCompilation.Create("a") .WithOptions(new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary)) .AddReferences( MetadataReference.CreateFromFile(typeof(object).GetTypeInfo().Assembly.Location)) .AddSyntaxTrees(CSharpSyntaxTree.ParseText( @" using System; public static class C { public static void M() { Console.WriteLine(""Hello Roslyn.""); } }")); var fileName = "a.dll"; compilation.Emit(fileName); var a = AssemblyLoadContext.Default.LoadFromAssemblyPath(Path.GetFullPath(fileName)); a.GetType("C").GetMethod("M").Invoke(null, null); 

选项#2 :使用Roslyn Scripting。 这将导致更简单的代码,但目前需要更多设置:

  • 创建NuGet.config以从Roslyn nightly feed获取包:

           
  • 将以下包作为依赖项添加到project.json(请注意,这是今天的包,将来需要不同的版本):

     "Microsoft.CodeAnalysis.CSharp.Scripting": "1.3.0-beta1-20160530-01", 

    您还需要导入dotnet (过时的“Target Framework Moniker”, 但仍然由Roslyn使用 ):

     "frameworks": { "netcoreapp1.0": { "imports": "dotnet5.6" } } 
  • 现在你可以最终使用Scripting了:

     CSharpScript.EvaluateAsync(@"using System;Console.WriteLine(""Hello Roslyn."");").Wait(); 

只需添加@svick选项一个答案。 如果要将程序集保留在内存中(而不是写入文件),可以使用以下方法:

 AssemblyLoadContext context = AssemblyLoadContext.Default; Assembly assembly = context.LoadFromStream(ms); 

这与Net451的不同之处在于代码为:

 Assembly assembly = Assembly.Load(ms.ToArray()); 

我的代码同时针对Net451和Netstandard,所以我不得不使用指令来解决这个问题。 完整的代码示例如下:

  string code = CreateFunctionCode(); var syntaxTree = CSharpSyntaxTree.ParseText(code); MetadataReference[] references = new MetadataReference[] { MetadataReference.CreateFromFile(typeof(object).GetTypeInfo().Assembly.Location), MetadataReference.CreateFromFile(typeof(Hashtable).GetTypeInfo().Assembly.Location) }; var compilation = CSharpCompilation.Create("Function.dll", syntaxTrees: new[] { syntaxTree }, references: references, options: new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary)); StringBuilder message = new StringBuilder(); using (var ms = new MemoryStream()) { EmitResult result = compilation.Emit(ms); if (!result.Success) { IEnumerable failures = result.Diagnostics.Where(diagnostic => diagnostic.IsWarningAsError || diagnostic.Severity == DiagnosticSeverity.Error); foreach (Diagnostic diagnostic in failures) { message.AppendFormat("{0}: {1}", diagnostic.Id, diagnostic.GetMessage()); } return new ReturnValue(false, "The following compile errors were encountered: " + message.ToString(), null); } else { ms.Seek(0, SeekOrigin.Begin); #if NET451 Assembly assembly = Assembly.Load(ms.ToArray()); #else AssemblyLoadContext context = AssemblyLoadContext.Default; Assembly assembly = context.LoadFromStream(ms); #endif Type mappingFunction = assembly.GetType("Program"); _functionMethod = mappingFunction.GetMethod("CustomFunction"); _resetMethod = mappingFunction.GetMethod("Reset"); } }