/// <summary> /// Compiles the start block of /// </summary> /// <param name="context"></param> public TypeInfo CompileNewProcessStart(CompileContext context, string name) { try { //Get this before we push a new type on the stack, we are going to need it... Dictionary <string, LocalBuilder> currentLocals = null; if (context.Type != null) { currentLocals = context.Type.Locals; } if (context.CurrentMasterType != null) //Are in a type, so let's create a nested one { TypeInfo nestedType = new TypeInfo(); nestedType.Builder = context.Type.Builder.DefineNestedType(name, TypeAttributes.NestedPublic | TypeAttributes.Class | TypeAttributes.BeforeFieldInit, typeof(ProcessBase)); context.PushType(nestedType); } else { context.PushType(context.GetType(name)); context.CurrentMasterType = context.Type; } Type baseType = typeof(ProcessBase); if (this.PreProcessActions != null) { this.PreProcessActions.Compile(context); context.Type.IsPreProcessed = true; } if (this.ActionRestrictions != null) { this.ActionRestrictions.Compile(context); context.Type.IsRestricted = true; } MethodBuilder methodStart = context.Type.Builder.DefineMethod("RunProcess", MethodAttributes.Public | MethodAttributes.Virtual); context.Type.Builder.DefineMethodOverride(methodStart, baseType.GetMethod("RunProcess")); context.PushIL(methodStart.GetILGenerator()); Call(new ThisPointer(typeof(ProcessBase)), "InitSetID", true).Compile(context); if (this.WrapInTryCatch) { context.ILGenerator.BeginExceptionBlock(); } if (context.Type.Constructor == null) //Nested type which hasn't defined its constructor yet { VariableCollection col = new VariableCollection(); col.Start(this); List <Type> paramTypes = new List <Type>(); List <Variable> constructorParams = new List <Variable>(); foreach (Variable v in col.Variables) { if (currentLocals != null && currentLocals.ContainsKey(v.Name)) //We have defined this local variable and so should pass it to the new process { paramTypes.Add(typeof(object)); constructorParams.Add(v); context.Type.ConstructorParameters.Add(v.Name); //Needed to pass the right parameters along later context.Type.Fields.Add(context.Type.Builder.DefineField(v.Name, typeof(object), FieldAttributes.Private)); } } context.Type.Constructor = context.Type.Builder.DefineConstructor(MethodAttributes.Public, CallingConventions.Standard, paramTypes.ToArray()); ILGenerator ilCon = context.Type.Constructor.GetILGenerator(); ilCon.Emit(OpCodes.Ldarg_0); ilCon.Emit(OpCodes.Call, typeof(ProcessBase).GetConstructor(new Type[] { })); for (int i = 0; i < constructorParams.Count; i++) { context.Type.Constructor.DefineParameter(i + 1, ParameterAttributes.None, constructorParams[i].Name); //save the variables argument we got passed in ilCon.Emit(OpCodes.Ldarg_0); ilCon.Emit(OpCodes.Ldarg, i + 1); ilCon.Emit(OpCodes.Stfld, context.Type.GetField(constructorParams[i].Name)); } ilCon.Emit(OpCodes.Ret); } //Do this after the constructor has been defined, because the fields //of the object are defined in the constructor... foreach (FieldBuilder field in context.Type.Fields) { LocalBuilder local = context.ILGenerator.DeclareLocal(typeof(object)); if (context.Options.Debug) { local.SetLocalSymInfo(field.Name); } context.Type.Locals.Add(field.Name, local); //Add the field value to the local variable, so we can concentrate on only local vars context.ILGenerator.Emit(OpCodes.Ldarg_0); context.ILGenerator.Emit(OpCodes.Ldfld, field); context.ILGenerator.Emit(OpCodes.Stloc, local); } return(context.Type); } catch (Exception) { return(null); } }