コード例 #1
0
        private void GenerateModuleAssembly()
        {
            #region GetVersion

            Version ver = BusinessBuilder.GetVersion(AdmiralEnvironment.UserDefineBusinessFile);

            if (ver != null)
            {
                ver = new Version(ver.Major + 1, ver.Minor, ver.Build, ver.Revision);
            }
            else
            {
                ver = new Version(1, 0, 0, 0);
            }

            #endregion

            var assemblyName = "AdmiralDynamicDC";
            var newFileName = AdmiralEnvironment.UserDefineBusinessTempFile.FullName;

            #region 定义程序集

            var asmName = new AssemblyNameDefinition(assemblyName, ver);
            //[assembly: AssemblyFileVersionAttribute("1.0.0.12")]
            var assembly =
                AssemblyDefinition.CreateAssembly(
                    asmName,
                    "MainModule",
                    ModuleKind.Dll
                    );
            //AppDomain.CurrentDomain.DefineDynamicAssembly(asmName, AssemblyBuilderAccess.Save, AdmiralEnvironment.UserDefineBusinessDirectoryInfo.FullName);

            #region 定义模块

            var module = assembly.MainModule;

            #endregion

            #endregion

            #region 设置文件版本

            var asmFileVerCtor = typeof(SR.AssemblyFileVersionAttribute).GetConstructor(new[] { typeof(string) });

            var asmFileVerCtorRef = assembly.MainModule.ImportReference(asmFileVerCtor);
            var ca = new Mono.Cecil.CustomAttribute(asmFileVerCtorRef);
            ca.ConstructorArguments.Add(new CustomAttributeArgument(
                assembly.MainModule.ImportReference(typeof(string)), ver.ToString()));
            assembly.CustomAttributes.Add(ca);

            #endregion

            #region XafModule

            var xafModule = new TypeDefinition("", "RuntimeModule",
                TypeAttributes.Public | TypeAttributes.Class,
                assembly.MainModule.ImportReference(typeof(RuntimeModuleBase)));

            //module.DefineType("RuntimeModule", TypeAttributes.Public | TypeAttributes.Class, typeof(RuntimeModuleBase));
            var ctor = new MethodDefinition(".ctor",
                MethodAttributes.Public
                | MethodAttributes.HideBySig
                | MethodAttributes.SpecialName
                | MethodAttributes.RTSpecialName,
                module.ImportReference(typeof(void))
                );
            //.method public hidebysig specialname rtspecialname instance void .ctor() cil managed

            //xafModule.DefineConstructor(MethodAttributes.Public, CallingConventions.Standard | CallingConventions.HasThis, Type.EmptyTypes);
            var baseCtor = typeof(RuntimeModuleBase).GetConstructor(Type.EmptyTypes);

            var il = ctor.Body.Instructions;

            //.maxstack 8
            //L_0000: ldarg.0
            //L_0001: call instance void Admiral.ERP.Module.RuntimeModuleBase::.ctor()
            //L_0006: ret
            il.Add(Instruction.Create(OpCodes.Ldarg_0));
            il.Add(Instruction.Create(OpCodes.Call, module.ImportReference(baseCtor)));
            il.Add(Instruction.Create(OpCodes.Ret));
            xafModule.Methods.Add(ctor);
            module.Types.Add(xafModule);

            #endregion

            #region 创建业务对象
            var ObjectSpace = this.Application.CreateObjectSpace();
            var allTypes = ObjectSpace.GetObjects<BusinessObjectBase>();

            var userDefinedBos = allTypes.OfType<BusinessObject>().Where(x => x.IsRuntimeDefine).ToList(); //ObjectSpace.GetObjects<BusinessObject>(new BinaryOperator("IsRuntimeDefine", true)).OrderBy(x => x.CreateIndex).ToArray();
            var dllTypes = allTypes.Except(userDefinedBos); //ObjectSpace.GetObjects<BusinessObject>(new BinaryOperator("IsRuntimeDefine", false));
            module.InitializeTypeReferences(dllTypes);

            //第一步只生成类型定义,是因为可能有交叉使用类型,如,基类是未定义的类型,则无法使用
            #region 定义类型生成的代码,包含属性修饰:-->[NonPersistent]pubic class {    }
            foreach (var bo in userDefinedBos)
            {
                var typeAtt = TypeAttributes.Class | TypeAttributes.Public;
                if (bo.IsAbstract)
                {
                    typeAtt |= TypeAttributes.Abstract;
                }
                else if (!bo.CanInherits)
                {
                    typeAtt |= TypeAttributes.Sealed;
                }

                var type = new TypeDefinition(bo.Category.FullName, bo.名称, typeAtt);
                module.Types.Add(type);

                if (!bo.IsPersistent)
                {
                    type.AddNonPersistentDc();
                }

                if (bo.IsCloneable.HasValue)
                {
                    type.ModelDefault("IsCloneable", bo.IsCloneable.Value.ToString().ToLower() );
                }

                if (bo.IsCreatableItem.HasValue)
                {
                    type.ModelDefault("IsCreatableItem", bo.IsCreatableItem.Value.ToString().ToLower());
                }

                if (bo.IsVisibileInReports.HasValue)
                {
                    type.VisibileInReport(bo.IsVisibileInReports.Value);
                }
                type.AddToTypeReferences(bo);
            }
            #endregion

            #region 生成剩下的内容
            foreach (var bo in userDefinedBos)
            {
                var type = bo.GetTypeDefintion();
                if (type == null)
                    throw new Exception("错误!");

                #region 处理基类

                var boBaseType = bo.Base.GetTypeReference() ?? module.ImportReference(typeof(SimpleObject));
                MethodReference boBaseCtor;

                if (boBaseType.HasGenericParameters)
                {
                    type.BaseType = boBaseType.MakeGenericType(bo.GenericParameters.Select(gp => gp.ParameterValue.GetTypeReference()).ToArray());

                    //var tb = boBaseType.Resolve().MakeGenericType(bo.GenericParameters.Select(gp => gp.ParameterValue.FindType(typeReferences)).ToArray());

                    boBaseCtor =
                        //(tb as TypeDefinition).Methods.Single(x => x.Name == ".ctor" && x.Parameters.First().ParameterType.FullName == typeof(Session).FullName);
                        module.ImportReference(
                            type.BaseType.Resolve()
                                .Methods.Single(
                                    x => x.Name == ".ctor" && x.Parameters.First().ParameterType.FullName == typeof(Session).FullName)
                            );
                    boBaseCtor = boBaseCtor.MakeGeneric(bo.GenericParameters.Select(gp => gp.ParameterValue.GetTypeReference()).ToArray());
                }
                else
                {
                    type.BaseType = boBaseType;
                    boBaseCtor = module.ImportReference(
                        boBaseType.Resolve().Methods.Single(x => x.Name == ".ctor" && x.Parameters.Count == 1 && x.Parameters.Single().ParameterType.FullName == typeof(Session).FullName)
                        );
                }

                if (boBaseCtor != null)
                {
                    var boctor = new MethodDefinition(".ctor",
                        MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig | MethodAttributes.RTSpecialName,
                        //CallingConventions.Standard | CallingConventions.HasThis,
                        module.ImportReference(typeof(void))
                        );
                    // type.DefineConstructor(MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig | MethodAttributes.RTSpecialName, CallingConventions.Standard | CallingConventions.HasThis, new Type[] { typeof(Session) });
                    var p = new ParameterDefinition("session", ParameterAttributes.None, module.ImportReference(typeof(Session)));
                    boctor.Parameters.Add(p);
                    var boil = boctor.Body.GetILProcessor();
                    //.GetILGenerator();

                    boil.Emit(OpCodes.Ldarg_0);
                    boil.Emit(OpCodes.Ldarg_1);
                    boil.Emit(OpCodes.Call, boBaseCtor);
                    boil.Emit(OpCodes.Nop);
                    boil.Emit(OpCodes.Nop);
                    boil.Emit(OpCodes.Ret);

                    //L_0000: ldarg.0
                    //L_0001: ldarg.1
                    //L_0002: call instance void IMatrix.ERP.Module.BusinessObjects.订单`1 <class IMatrix.ERP.Module.BusinessObjects.PMS.采购订单明细>::.ctor(class [DevExpress.Xpo.v15.2]
                    //DevExpress.Xpo.Session)
                    //L_0007: nop
                    //L_0008: nop
                    //L_0009: ret

                    //.method public hidebysig specialname rtspecialname
                    //instance void  .ctor(class ['DevExpress.Xpo.v15.2']DevExpress.Xpo.Session session) cil managed
                    //{
                    //// 代码大小       10 (0xa)
                    //.maxstack  8
                    //IL_0000:  ldarg.0
                    //IL_0001:  ldarg.1
                    //IL_0002:  call       instance void [IMatrix.ERP.Module]IMatrix.ERP.Module.BusinessObjects.'订单`1'::.ctor<class '业务'.'采购计划明细'>(class ['DevExpress.Xpo.v15.2']DevExpress.Xpo.Session)
                    //IL_0007:  nop
                    //IL_0008:  nop
                    //IL_0009:  ret
                    //} // end of method '采购计划'::.ctor

                    type.Methods.Add(boctor);
                }

                #endregion

                #region 填加属性

                foreach (var p in bo.Properties)
                {
                    BuildPropertyCore(p, type);
                }

                #endregion

                #region 填加集合属性
                foreach (var item in bo.CollectionProperties)
                {
                    BuildCollectionProperty(item, type);
                }
                #endregion
            }
            #endregion

            #endregion

            #region 保存生成的程序集
            assembly.Write(newFileName);
            #endregion

            #region 删除模块信息,让系统执行更新表结构动作

            var moduleInfo = ObjectSpace.FindObject<ModuleInfo>(new BinaryOperator("Name", "RuntimeModule"));
            if (moduleInfo != null)
            {
                ObjectSpace.Delete(moduleInfo);
                ObjectSpace.CommitChanges();
            }
            var restart = Application as IRestartApplication;
            if (restart != null)
            {
                restart.RestartApplication();
            }
            #endregion
        }