Compiling and Running code at runtime in .Net Core 1.0

后端 未结 3 550
再見小時候
再見小時候 2020-12-03 03:39

Is it possible to compile and run C# code at runtime in the new .Net Core (better .Net Standard Platform)? I have seen some examples (.Net Framework), but they used NuGet pa

3条回答
  •  天命终不由人
    2020-12-03 04:03

    Both previous answers didn't work for me in .NET Core 2.2 environment on Windows. More references are needed.

    So with the help of https://stackoverflow.com/a/39260735/710069 solution, I have ended up with this code:

    var dotnetCoreDirectory = System.Runtime.InteropServices.RuntimeEnvironment.GetRuntimeDirectory();
    
    var compilation = CSharpCompilation.Create("LibraryName")
        .WithOptions(new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary))
        .AddReferences(
            MetadataReference.CreateFromFile(typeof(object).GetTypeInfo().Assembly.Location),
            MetadataReference.CreateFromFile(typeof(Console).GetTypeInfo().Assembly.Location),
            MetadataReference.CreateFromFile(Path.Combine(dotnetCoreDirectory, "mscorlib.dll")),
            MetadataReference.CreateFromFile(Path.Combine(dotnetCoreDirectory, "netstandard.dll")),
            MetadataReference.CreateFromFile(Path.Combine(dotnetCoreDirectory, "System.Runtime.dll")))
        .AddSyntaxTrees(CSharpSyntaxTree.ParseText(
            @"public static class ClassName 
            { 
                public static void MethodName() => System.Console.WriteLine(""Hello C# Compilation."");
            }"));
    
    // Debug output. In case your environment is different it may show some messages.
    foreach (var compilerMessage in compilation.GetDiagnostics())
        Console.WriteLine(compilerMessage);
    

    Than output library to file:

    var fileName = "LibraryName.dll";
    var emitResult = compilation.Emit(fileName);
    if (emitResult.Success)
    {
        var assembly = AssemblyLoadContext.Default.LoadFromAssemblyPath(Path.GetFullPath(fileName));
    
        assembly.GetType("ClassName").GetMethod("MethodName").Invoke(null, null);
    }
    

    or to memory stream:

    using (var memoryStream = new MemoryStream())
    {
        var emitResult = compilation.Emit(memoryStream);
        if (emitResult.Success)
        {
            memoryStream.Seek(0, SeekOrigin.Begin);
    
            var context = AssemblyLoadContext.Default;
            var assembly = context.LoadFromStream(memoryStream);
    
            assembly.GetType("ClassName").GetMethod("MethodName").Invoke(null, null);
        }
    }
    

提交回复
热议问题