.NET 5 动态编译

    /// <summary>
    /// 编译程序
    /// </summary>
    public static class CompileAssembly
    {
        /// <summary>
        /// 从代码中编译出类型(.net core ++ 版本平台不支持)
        /// </summary>
        /// <param name="sources"></param>
        /// <returns></returns>
        public static List<Type> CompileAssemblyFromSource(string sources)
        {
#if NET5_0
            return NetCore(sources);
#endif
#if NET45
           return NetFramework(sources);
#endif
        }
        private static List<Type> NetFramework(string sources)
        {
            var providerOptions = new Dictionary<string, string>();
            providerOptions.Add("CompilerVersion", "v4.0");
            CSharpCodeProvider compiler = new CSharpCodeProvider(providerOptions);
            string output = Path.GetTempFileName();
            var cp = new CompilerParameters() { GenerateInMemory = true, OutputAssembly = output };
            cp.ReferencedAssemblies.Add(Assembly.GetExecutingAssembly().Location);
            cp.ReferencedAssemblies.Add("Microsoft.CSharp.dll");
            cp.ReferencedAssemblies.Add("System.Core.dll");
            cp.ReferencedAssemblies.Add("System.dll");
            cp.GenerateExecutable = false;
            cp.EmbeddedResources.Clear();
            cp.LinkedResources.Clear();
            cp.Win32Resource = null;
            cp.TreatWarningsAsErrors = false;
            cp.WarningLevel = 4;
            cp.TempFiles.KeepFiles = false;
            var ass = compiler.CompileAssemblyFromSource(cp, sources);
            if (ass.Errors.HasErrors)
            {
                List<string> erros = new List<string>();
                for (var i = 0; i < ass.Errors.Count; i++)
                {
                    erros.Add(ass.Errors[i].ErrorText);
                }
                throw new XmlSqlParseException { Errors = erros };
            }
            return ass.CompiledAssembly.GetTypes().Where(v => v.GetCustomAttribute<SqlAttribute>() != null).ToList();
        }
        private static List<Type> NetCore(string sources)
        {
            SyntaxTree syntaxTree = CSharpSyntaxTree.ParseText(sources);
            string output = Path.GetTempFileName();
            string assemblyName = Path.GetFileName(output);
            var refPaths = new[] {
                Assembly.GetExecutingAssembly().Location,
                typeof(object).GetTypeInfo().Assembly.Location,
                Path.Combine(Path.GetDirectoryName(typeof(System.Runtime.GCSettings).GetTypeInfo().Assembly.Location), "System.Runtime.dll"),
                typeof(DynamicAttribute).GetTypeInfo().Assembly.Location,
            };
            MetadataReference[] references = refPaths.Select(r => MetadataReference.CreateFromFile(r)).ToArray();
            CSharpCompilation compilation = CSharpCompilation.Create(assemblyName, syntaxTrees: new[] { syntaxTree }, references: references, options: new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary));
            var compilationResult = compilation.Emit(output);
            if (compilationResult.Success)
            {
                try
                {
                    byte[] assemblyBytes = File.ReadAllBytes(output);
                    var ass = Assembly.Load(assemblyBytes);
                    return ass.GetTypes().ToList();
                }
                finally
                {
                    File.Delete(output);
                }
            }
            var error = new StringBuilder(compilationResult.Diagnostics.Length * 1024);
            foreach (var t in compilationResult.Diagnostics)
            {
                error.AppendLine($"{t.GetMessage()}");
            }
            throw new XmlSqlParseException { Errors = new List<string>() { $"所选文件编译有错误{Environment.NewLine}{error}" } };
        }
    }

posted @ 2022-01-11 15:56  蓝创精英团队  阅读(5)  评论(0)    收藏  举报  来源