Is it possible to dynamically compile and execute C# code fragments?

后端 未结 6 1718
伪装坚强ぢ
伪装坚强ぢ 2020-11-21 07:10

I was wondering if it is possible to save C# code fragments to a text file (or any input stream), and then execute those dynamically? Assuming what is provided to me would c

6条回答
  •  囚心锁ツ
    2020-11-21 07:35

    You can compile a piece C# of code into memory and generate assembly bytes with Roslyn. It's already mentioned but would be worth adding some Roslyn example for this here. The following is the complete example:

    using System;
    using System.Collections.Generic;
    using System.IO;
    using System.Linq;
    using System.Reflection;
    using Microsoft.CodeAnalysis;
    using Microsoft.CodeAnalysis.CSharp;
    using Microsoft.CodeAnalysis.Emit;
    
    namespace RoslynCompileSample
    {
        class Program
        {
            static void Main(string[] args)
            {
                // define source code, then parse it (to the type used for compilation)
                SyntaxTree syntaxTree = CSharpSyntaxTree.ParseText(@"
                    using System;
    
                    namespace RoslynCompileSample
                    {
                        public class Writer
                        {
                            public void Write(string message)
                            {
                                Console.WriteLine(message);
                            }
                        }
                    }");
    
                // define other necessary objects for compilation
                string assemblyName = Path.GetRandomFileName();
                MetadataReference[] references = new MetadataReference[]
                {
                    MetadataReference.CreateFromFile(typeof(object).Assembly.Location),
                    MetadataReference.CreateFromFile(typeof(Enumerable).Assembly.Location)
                };
    
                // analyse and generate IL code from syntax tree
                CSharpCompilation compilation = CSharpCompilation.Create(
                    assemblyName,
                    syntaxTrees: new[] { syntaxTree },
                    references: references,
                    options: new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary));
    
                using (var ms = new MemoryStream())
                {
                    // write IL code into memory
                    EmitResult result = compilation.Emit(ms);
    
                    if (!result.Success)
                    {
                        // handle exceptions
                        IEnumerable failures = result.Diagnostics.Where(diagnostic => 
                            diagnostic.IsWarningAsError || 
                            diagnostic.Severity == DiagnosticSeverity.Error);
    
                        foreach (Diagnostic diagnostic in failures)
                        {
                            Console.Error.WriteLine("{0}: {1}", diagnostic.Id, diagnostic.GetMessage());
                        }
                    }
                    else
                    {
                        // load this 'virtual' DLL so that we can use
                        ms.Seek(0, SeekOrigin.Begin);
                        Assembly assembly = Assembly.Load(ms.ToArray());
    
                        // create instance of the desired class and call the desired function
                        Type type = assembly.GetType("RoslynCompileSample.Writer");
                        object obj = Activator.CreateInstance(type);
                        type.InvokeMember("Write",
                            BindingFlags.Default | BindingFlags.InvokeMethod,
                            null,
                            obj,
                            new object[] { "Hello World" });
                    }
                }
    
                Console.ReadLine();
            }
        }
    }
    

提交回复
热议问题