private string GeneratorCode(TypesAndReferences threadParam)
        {
            //测试ERP258系统,1253个实体类,5线程编译,每线程的StringBuilder长度数据如下:
            //3826393,4451978,3653788,4433206,4545317
            //根据以上数字,初始值设置为1024*1024*5
            StringBuilder sb = new StringBuilder(1024 * 1024 * 5);

            // 生成命名空间和命名空间的引用
            sb.AppendLine(CodeGenerator.GetCodeHeader());

            // 生成一个工具类
            sb.AppendLine(CodeGenerator.GetCodeUtil());

            // 为每个数据实体类型生成数据访问代码
            foreach (Type type in threadParam.EntityTypes)
            {
                CodeGenerator generator = new CodeGenerator(type);

                // 数据访问代码的类型名称根据数据实体名称得到,具体生成方法请参考下面这行代码。
                string className = "CodeDom_" + type.FullName.Replace(".", "_");

                // 生成数据访问代码。
                string code = generator.GetCode(className);
                sb.AppendLine(code);
            }

            sb.Append("}");

            return(sb.ToString());
        }
Beispiel #2
0
        public static void StartAutoCompile()
        {
            // 1. 查找所有的数据实体类型
            TypesAndReferences findResult = FindEntityTypes();

            // 2. 批量编译数据实体
            BatchCompile(findResult);
        }
        public void DoWork(object obj)
        {
            TypesAndReferences threadParam = (TypesAndReferences)obj;

            try {
                // 1. 生成代码
                string code = GeneratorCode(threadParam);

                // 2. 编译生成的代码
                Assembly assembly = CompilerCode(code, threadParam.ReferencedAssemblies);

                // 3. 创建委托,供后续代码调用
                CreateDelegate(threadParam.EntityTypes, assembly);
            }
            catch (System.Exception ex) {
                BuildManager.AddException(ex);
            }
        }
Beispiel #4
0
        private static TypesAndReferences FindEntityTypes()
        {
            string runtimeFolder = BinDirectory;

            List <Assembly> assemblies = new List <Assembly>();

            // 只搜索所有以【.Entity.dll】结尾的程序集
            string searchPattern = System.Configuration.ConfigurationManager.AppSettings["MapExt-DAL:EntityDllSearchPattern"];

            if (string.IsNullOrEmpty(searchPattern))
            {
                searchPattern = "*.Entity.dll";
            }

            foreach (string file in Directory.GetFiles(runtimeFolder, searchPattern, SearchOption.TopDirectoryOnly))
            {
                assemblies.Add(Assembly.LoadFile(file));
            }


            List <string> assemblyList = new List <string>();
            List <Type>   types        = new List <Type>();

            Type typeBaseEntity    = typeof(BaseEntity);
            Type typeBaseEntityOfT = typeof(BaseEntity <>);

            foreach (Assembly assembly in assemblies)
            {
                // 保存程序集的引用
                assemblyList.Add(assembly.Location);

                foreach (Type type in assembly.GetExportedTypes())
                {
                    // 查找所有 BaseEntity 的继承类,并且【排除嵌套类型】。
                    if (type.IsSubclassOf(typeBaseEntity) || type.IsSubclassOf(typeBaseEntityOfT))
                    {
                        if (type.IsNested == false)
                        {
                            // 数据实体类型要求提供【无参构造函数】。
                            if (type.GetConstructor(Type.EmptyTypes) == null)
                            {
                                throw new InvalidProgramException(string.Format("类型 {0} 没有定义无参的构造函数 。", type));
                            }

                            // 保留符合所有条件的数据实体类型,它将被编译
                            types.Add(type);
                        }
                    }
                }
            }

            // 添加必要的其它引用程序集,供编译使用
            assemblyList.Add("System.dll");
            assemblyList.Add("System.Xml.dll");
            assemblyList.Add("System.Web.dll");
            assemblyList.Add("System.Data.dll");
            assemblyList.Add(typeof(Panto.Map.Extensions.CodeDom.BuildManager).Assembly.Location);

            // 构造返回结果
            TypesAndReferences result = new TypesAndReferences();

            result.EntityTypes          = types;
            result.ReferencedAssemblies = assemblyList.ToArray();
            return(result);
        }
Beispiel #5
0
        private static void BatchCompile(TypesAndReferences findResult)
        {
            //findResult.EntityTypes = findResult.EntityTypes.Take(200).ToList();

            int typeCount = findResult.EntityTypes.Count;

            //如果小于或等于容器大小.则无需开启线程编译
            if (typeCount <= Number200)
            {
                CodeDomCompiler compiler = new CodeDomCompiler();
                compiler.DoWork(findResult);
            }
            else
            {
                // 计算编译线程数量
                int threadCount = typeCount % Number200 == 0 ? typeCount / Number200 : typeCount / Number200 + 1;
                if (threadCount > MaxThreadCount)
                {
                    threadCount = MaxThreadCount;
                }


                int threadPqgeSize = (typeCount / threadCount) + 1;
                int typeSum        = 0;

                // 为每个线程准备调用参数
                TypesAndReferences[] parameters = new TypesAndReferences[threadCount];
                for (int i = 0; i < threadCount; i++)
                {
                    parameters[i] = new TypesAndReferences();
                    parameters[i].ReferencedAssemblies = (from s in findResult.ReferencedAssemblies select s).ToArray();
                    parameters[i].EntityTypes          = findResult.EntityTypes.Skip(typeSum).Take(threadPqgeSize).ToList();
                    typeSum += parameters[i].EntityTypes.Count;
                }

                // 创建编译线程
                List <Thread> threads = new List <Thread>(threadCount);
                for (int i = 1; i < threadCount; i++)
                {
                    CodeDomCompiler compiler = new CodeDomCompiler();
                    Thread          thread   = new Thread(compiler.DoWork);
                    thread.IsBackground = true;
                    thread.Name         = "CompilerThread #" + i.ToString();
                    threads.Add(thread);
                    thread.Start(parameters[i]);
                }

                // 重用当前线程:为当前线程指派编译任务。
                CodeDomCompiler compiler2 = new CodeDomCompiler();
                compiler2.DoWork(parameters[0]);


                // 等待所有的编译线程执行线束。
                foreach (Thread thread in threads)
                {
                    thread.Join();
                }
            }

            // 如果在编译期间发生了异常,则抛出所有收集到的异常。
            if (s_buildException.BuildExceptions.Count > 0)
            {
                throw s_buildException;
            }
        }