Пример #1
0
        /// <summary>
        /// 使用内存流进行脚本编译
        /// </summary>
        /// <param name="content">脚本内容</param>
        /// <param name="errorAction">发生错误执行委托</param>
        /// <returns></returns>
        public static Assembly StreamComplier(string content, Action <Diagnostic> errorAction = null)
        {
            content = content.Trim();
            var(Tree, ClassName, formatter) = GetTreeAndClassNames(content);
            StringBuilder recoder = new StringBuilder(formatter);


            //创建语言编译
            CSharpCompilation compilation = CSharpCompilation.Create(
                ClassName[0],
                options: new CSharpCompilationOptions(
                    outputKind: OutputKind.DynamicallyLinkedLibrary,
                    optimizationLevel: OptimizationLevel.Release),
                syntaxTrees: new[] { Tree },
                references: References);


            //编译并生成程序集
            using (MemoryStream stream = new MemoryStream())
            {
                var fileResult = compilation.Emit(stream);
                if (fileResult.Success)
                {
                    stream.Position = 0;
                    AssemblyLoadContext context = AssemblyLoadContext.Default;
                    var result = context.LoadFromStream(stream);


                    if (NScriptLog.UseLog)
                    {
                        recoder.AppendLine("\r\n\r\n------------------------------------------succeed-------------------------------------------");
                        recoder.AppendLine($"\r\n    Time :\t\t{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}");
                        recoder.AppendLine($"\r\n    Lauguage :\t{compilation.Language} & {compilation.LanguageVersion}");
                        recoder.AppendLine($"\r\n    Target :\t\t{ClassName}");
                        recoder.AppendLine($"\r\n    Size :\t\t{stream.Length}");
                        recoder.AppendLine($"\r\n    Assembly : \t{result.FullName}");
                        recoder.AppendLine("\r\n----------------------------------------------------------------------------------------------");
                        NScriptLog.Succeed("Succeed : " + ClassName, recoder.ToString());
                    }


                    return(result);
                }
                else
                {
                    if (NScriptLog.UseLog)
                    {
                        recoder.AppendLine("\r\n\r\n------------------------------------------error----------------------------------------------");
                        recoder.AppendLine($"\r\n    Time :\t\t{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}");
                        recoder.AppendLine($"\r\n    Lauguage :\t{compilation.Language} & {compilation.LanguageVersion}");
                        recoder.AppendLine($"\r\n    Target:\t\t{ClassName}");
                        recoder.AppendLine($"\r\n    Error:\t\t共{fileResult.Diagnostics.Length}处错误!");
                    }

                    //错误处理
                    foreach (var item in fileResult.Diagnostics)
                    {
                        if (NScriptLog.UseLog)
                        {
                            var temp   = item.Location.GetLineSpan().StartLinePosition;
                            var result = GetErrorString(formatter, item.Location.GetLineSpan());
                            recoder.AppendLine($"\t\t第{temp.Line + 1}行,第{temp.Character}个字符:       内容【{result}】  {item.GetMessage()}");
                        }

                        errorAction?.Invoke(item);
                    }


                    if (NScriptLog.UseLog)
                    {
                        recoder.AppendLine("\r\n---------------------------------------------------------------------------------------------");
                        NScriptLog.Error("Error : " + ClassName, recoder.ToString());
                    }
                }
            }


            return(null);
        }
Пример #2
0
        /// <summary>
        /// 使用文件流进行脚本编译,根据类名生成dll
        /// </summary>
        /// <param name="content">脚本内容</param>
        /// <param name="errorAction">发生错误执行委托</param>
        /// <returns></returns>
        public static Assembly FileComplier(string content, Action <Diagnostic> errorAction = null)
        {
            StringBuilder recoder = new StringBuilder(LineFormat(ref content));


            //类名获取
            var(Tree, ClassNames) = GetTreeAndClassNames(content);


            //生成路径
            string path = $"{LibPath}{ClassNames[0]}.dll";


            if (DynamicDlls.ContainsKey(path))
            {
                return(DynamicDlls[path]);
            }


            //写入分析树
            //SyntaxTree tree = SyntaxFactory.ParseSyntaxTree(content);

            //创建语言编译
            CSharpCompilation compilation = CSharpCompilation.Create(
                ClassNames[0],
                options: new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary),
                syntaxTrees: new[] { Tree },
                references: References);


            EmitResult fileResult;

            //编译到文件
            try
            {
                fileResult = compilation.Emit(path);
            }
            catch (Exception ex)
            {
                if (ex is IOException)
                {
                    int loop = 0;
                    while (!DynamicDlls.ContainsKey(path))
                    {
                        Thread.Sleep(200);
                        loop += 1;
                    }

                    NScriptLog.Warning(ClassNames[0], $"    I/O Delay :\t检测到争用,延迟{loop * 200}ms调用;\r\n");

                    return(DynamicDlls[path]);
                }
                return(null);
            }

            if (fileResult.Success)
            {
                References.Add(MetadataReference.CreateFromFile(path));
                //为了实现动态中的动态,使用文件加载模式常驻内存
                var result = Assembly.LoadFrom(path);
                for (int i = 0; i < ClassNames.Length; i += 1)
                {
                    ClassMapping[ClassNames[i]] = result;
                }

                if (NScriptLog.UseLog)
                {
                    recoder.AppendLine("\r\n\r\n------------------------------------------succeed-------------------------------------------");
                    recoder.AppendLine($"\r\n    Lauguage :\t{compilation.Language}___{compilation.LanguageVersion}");
                    recoder.AppendLine($"\r\n    Target :\t\t{ClassNames[0]}");
                    recoder.AppendLine($"\r\n    Path :\t\t{path}");
                    recoder.AppendLine($"\r\n    Assembly : \t{result.FullName}");
                    recoder.AppendLine("\r\n----------------------------------------------------------------------------------------------");
                    NScriptLog.Succeed("Succeed : " + ClassNames[0], recoder.ToString());
                }


                DynamicDlls[path] = result;
                return(result);
            }
            else
            {
                if (NScriptLog.UseLog)
                {
                    recoder.AppendLine("\r\n\r\n------------------------------------------error----------------------------------------------");
                    recoder.AppendLine($"\r\n    Lauguage :\t{compilation.Language}___{compilation.LanguageVersion}");
                    recoder.AppendLine($"\r\n    Target:\t\t{ClassNames[0]}");
                    recoder.AppendLine($"\r\n    Error:\t\t共{fileResult.Diagnostics.Length}处错误!");
                }

                foreach (var item in fileResult.Diagnostics)
                {
                    if (NScriptLog.UseLog)
                    {
                        var temp   = item.Location.GetLineSpan().StartLinePosition;
                        var result = GetErrorString(content, item.Location.GetLineSpan());
                        recoder.AppendLine($"\t\t第{temp.Line}行,第{temp.Character}个字符:       内容【{result}】  {item.GetMessage()}");
                    }
                    errorAction?.Invoke(item);
                }


                recoder.AppendLine("\r\n---------------------------------------------------------------------------------------------");
                NScriptLog.Error("Error : " + ClassNames[0], recoder.ToString());
            }
            return(null);
        }
Пример #3
0
        /// <summary>
        /// 使用文件流进行脚本编译,根据类名生成dll
        /// </summary>
        /// <param name="content">脚本内容</param>
        /// <param name="errorAction">发生错误执行委托</param>
        /// <returns></returns>
        public static Assembly FileComplier(string content, Action <Diagnostic> errorAction = null)
        {
            //类名获取
            content = content.Trim();
            var(Tree, ClassNames, formatter) = GetTreeAndClassNames(content);
            StringBuilder recoder = new StringBuilder(FormatLineCode(formatter));


            //生成路径
            string path = Path.Combine(LibPath, $"{ClassNames[0]}.dll");

            if (DynamicDlls.ContainsKey(path))
            {
                return(DynamicDlls[path]);
            }


            //创建语言编译
            CSharpCompilation compilation = CSharpCompilation.Create(
                ClassNames[0],
                options: new CSharpCompilationOptions(
                    outputKind: OutputKind.DynamicallyLinkedLibrary,
                    optimizationLevel: OptimizationLevel.Release),
                syntaxTrees: new[] { Tree },
                references: References);


            EmitResult fileResult;

            //编译到文件
            try
            {
                fileResult = compilation.Emit(path);
                if (fileResult.Success)
                {
                    //为了实现动态中的动态,使用文件加载模式常驻内存
                    AssemblyLoadContext context = AssemblyLoadContext.Default;
                    var result = context.LoadFromAssemblyPath(path);
                    References.Add(MetadataReference.CreateFromFile(path));


                    for (int i = 0; i < ClassNames.Length; i += 1)
                    {
                        ClassMapping[ClassNames[i]] = result;
                    }

                    if (NScriptLog.UseLog)
                    {
                        recoder.AppendLine("\r\n\r\n------------------------------------------succeed-------------------------------------------");
                        recoder.AppendLine($"\r\n    Time :\t\t{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}");
                        recoder.AppendLine($"\r\n    Lauguage :\t{compilation.Language} & {compilation.LanguageVersion}");
                        recoder.AppendLine($"\r\n    Target :\t\t{ClassNames[0]}");
                        recoder.AppendLine($"\r\n    Path :\t\t{path}");
                        recoder.AppendLine($"\r\n    Assembly : \t{result.FullName}");
                        recoder.AppendLine("\r\n----------------------------------------------------------------------------------------------");
                        NScriptLog.Succeed("Succeed : " + ClassNames[0], recoder.ToString());
                    }


                    DynamicDlls[path] = result;
                    return(result);
                }
                else
                {
                    if (NScriptLog.UseLog)
                    {
                        recoder.AppendLine("\r\n\r\n------------------------------------------error----------------------------------------------");
                        recoder.AppendLine($"\r\n    Time :\t\t{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}");
                        recoder.AppendLine($"\r\n    Lauguage :\t{compilation.Language} & {compilation.LanguageVersion}");
                        recoder.AppendLine($"\r\n    Target:\t\t{ClassNames[0]}");
                        recoder.AppendLine($"\r\n    Error:\t\t共{fileResult.Diagnostics.Length}处错误!");
                    }

                    foreach (var item in fileResult.Diagnostics)
                    {
                        if (NScriptLog.UseLog)
                        {
                            var temp   = item.Location.GetLineSpan().StartLinePosition;
                            var result = GetErrorString(formatter, item.Location.GetLineSpan());
                            recoder.AppendLine($"\t\t第{temp.Line + 1}行,第{temp.Character}个字符:       内容【{result}】  {item.GetMessage()}");
                        }
                        errorAction?.Invoke(item);
                    }


                    recoder.AppendLine("\r\n---------------------------------------------------------------------------------------------");
                    NScriptLog.Error("Error : " + ClassNames[0], recoder.ToString());
                }


                return(null);
            }
            catch (Exception ex)
            {
                if (ex is IOException)
                {
                    int loop = 0;
                    while (!DynamicDlls.ContainsKey(path))
                    {
                        Thread.Sleep(200);
                        loop += 1;
                    }


                    NScriptLog.Warning(ClassNames[0], $"    I/O Delay :\t检测到争用,延迟{loop * 200}ms调用;\r\n");


                    return(DynamicDlls[path]);
                }


                return(null);
            }
        }
Пример #4
0
        /// <summary>
        /// 使用内存流进行脚本编译
        /// </summary>
        /// <param name="content">脚本内容</param>
        /// <param name="errorAction">发生错误执行委托</param>
        /// <returns></returns>
        public static Assembly StreamComplier(string content, Action <Diagnostic> errorAction = null)
        {
            StringBuilder recoder = new StringBuilder(LineFormat(ref content));

            var(Tree, ClassName) = GetTreeAndClassName(content);


            //创建语言编译
            CSharpCompilation compilation = CSharpCompilation.Create(
                ClassName,
                options: new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary),
                syntaxTrees: new[] { Tree },
                references: References);


            //编译并生成程序集
            using (MemoryStream stream = new MemoryStream())
            {
                var fileResult = compilation.Emit(stream);
                if (fileResult.Success)
                {
                    var result = Assembly.Load(stream.GetBuffer());

                    if (NScriptLog.UseLog)
                    {
                        recoder.AppendLine("\r\n\r\n------------------------------------------succeed-------------------------------------------");
                        recoder.AppendLine($"\r\n    Lauguage :\t{compilation.Language}___{compilation.LanguageVersion}");
                        recoder.AppendLine($"\r\n    Target :\t\t{ClassName}");
                        recoder.AppendLine($"\r\n    Size :\t\t{stream.Length}");
                        recoder.AppendLine($"\r\n    Assembly : \t{result.FullName}");
                        recoder.AppendLine("\r\n----------------------------------------------------------------------------------------------");
                        NScriptLog.Succeed("Succeed : " + ClassName, recoder.ToString());
                    }


                    return(result);
                }
                else
                {
                    if (NScriptLog.UseLog)
                    {
                        recoder.AppendLine("\r\n\r\n------------------------------------------error----------------------------------------------");
                        recoder.AppendLine($"\r\n    Lauguage :\t{compilation.Language}___{compilation.LanguageVersion}");
                        recoder.AppendLine($"\r\n    Target:\t\t{ClassName}");
                        recoder.AppendLine($"\r\n    Error:\t\t共{fileResult.Diagnostics.Length}处错误!");
                    }

                    //错误处理
                    foreach (var item in fileResult.Diagnostics)
                    {
                        if (NScriptLog.UseLog)
                        {
                            var temp   = item.Location.GetLineSpan().StartLinePosition;
                            var result = GetErrorString(content, item.Location.GetLineSpan());
                            recoder.AppendLine($"\t\t第{temp.Line}行,第{temp.Character}个字符:       内容【{result}】  {item.GetMessage()}");
                        }
                        errorAction?.Invoke(item);
                    }

                    if (NScriptLog.UseLog)
                    {
                        recoder.AppendLine("\r\n---------------------------------------------------------------------------------------------");
                        NScriptLog.Error("Error : " + ClassName, recoder.ToString());
                    }
                }
            }


            return(null);
        }