是否有可能在新的.Net核心(更好的.Net標準平臺)中運行時編譯和運行c#代碼?我見過一些例子(.Net框架),但使用的NuGet包有在.Net核心1.0中運行時編譯和運行代碼
不兼容netcoreapp1.0(.NETCoreApp,版本= V1.0)
是否有可能在新的.Net核心(更好的.Net標準平臺)中運行時編譯和運行c#代碼?我見過一些例子(.Net框架),但使用的NuGet包有在.Net核心1.0中運行時編譯和運行代碼
不兼容netcoreapp1.0(.NETCoreApp,版本= 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:使用羅斯林腳本。這將導致更簡單的代碼,但目前需要更多的設置:
創建NuGet.config從羅斯林夜間進得包:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<packageSources>
<add key="Roslyn Nightly" value="https://www.myget.org/F/roslyn-nightly/api/v3/index.json" />
</packageSources>
</configuration>
添加下面的包作爲一個依賴關係project.json(請注意,這是包從今天起,您將需要在未來不同的版本):
"Microsoft.CodeAnalysis.CSharp.Scripting": "1.3.0-beta1-20160530-01",
您還需要導入dotnet
(過時的 「目標框架名字對象」,which is nevertheless still used by Roslyn):
"frameworks": {
"netcoreapp1.0": {
"imports": "dotnet5.6"
}
}
現在你終於可以使用腳本:
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<Diagnostic> 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<MethodInfo>(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");
}
}
'.Net核心'中不存在AssemblyLoadContext' –
@AlexZhukovskiy AssemblyLoadContext只存在於.Net核心,在'System.Runtime.Loader'包中。 – svick
非常感謝! – Mottor
你能看到我的其他問題嗎? http://stackoverflow.com/questions/37482955/how-can-i-use-net-core-class-library-netstandard-v1-5-int-net-framework-4 – Mottor
你的例子工作正常,但它是不可能用參數添加'ReadLine'或'WriteLine'。我在哪裏可以獲得有關重載和方法存在的文檔?因爲Console具有Write方法但沒有任何ReadLine時非常奇怪。 –