Example #1
0
        static void AddField(ModuleDefinition module, NewFieldData newField)
        {
            var fieldType   = GenTypes.GetTypeInAnyAssembly(newField.fieldType);
            var ceFieldType = module.ImportReference(fieldType);

            PrepatcherMod.Info($"Patching in a new field {newField.name} of type {ceFieldType.ToStringSafe()}/{newField.fieldType} in type {newField.targetType}");

            var ceField = new FieldDefinition(
                newField.name,
                FieldAttributes.Public,
                ceFieldType
                );

            if (newField.isStatic)
            {
                ceField.Attributes |= FieldAttributes.Static;
            }

            var targetType = module.GetType(newField.targetType);

            targetType.Fields.Add(ceField);

            if (newField.defaultValue != null)
            {
                WriteFieldInitializers(newField, ceField, fieldType);
            }
        }
Example #2
0
        static void WriteFieldInitializers(NewFieldData newField, FieldDefinition ceNewField, Type fieldType)
        {
            var targetType = ceNewField.DeclaringType;
            var i          = targetType.Fields.IndexOf(ceNewField);

            foreach (var ctor in targetType.GetConstructors().Where(c => c.IsStatic == newField.isStatic))
            {
                if (Util.CallsAThisCtor(ctor))
                {
                    continue;
                }

                var insts     = (IList <Instruction>)ctor.Body.Instructions;
                int insertAt  = -1;
                int lastValid = -1;

                for (int k = 0; k < insts.Count; k++)
                {
                    var inst = insts[k];
                    insertAt = lastValid;

                    if (inst.OpCode == OpCodes.Call && inst.Operand is MethodDefinition m && m.IsConstructor)
                    {
                        break;
                    }

                    if (inst.OpCode == OpCodes.Stfld && inst.Operand is FieldDefinition f)
                    {
                        if (targetType.Fields.IndexOf(f) > i)
                        {
                            break;
                        }

                        lastValid = k;
                    }
                }

                insertAt++;

                var ilProc       = ctor.Body.GetILProcessor();
                var insertBefore = insts[insertAt];

                if (!newField.isStatic)
                {
                    ilProc.InsertBefore(insertBefore, Instruction.Create(OpCodes.Ldarg_0));
                }

                if (newField.defaultValue == NewFieldData.DEFAULT_VALUE_NEW_CTOR)
                {
                    ilProc.InsertBefore(insertBefore, Instruction.Create(OpCodes.Newobj, targetType.Module.ImportReference(fieldType.GetConstructor(new Type[0]))));
                }
                else
                {
                    var defaultValueInst = Instruction.Create(OpCodes.Ret);
                    var op = Util.GetConstantOpCode(newField.defaultValue).Value;
                    defaultValueInst.OpCode  = op;
                    defaultValueInst.Operand = op == OpCodes.Ldc_I4 ? Convert.ToInt32(newField.defaultValue) : newField.defaultValue;

                    ilProc.InsertBefore(insertBefore, defaultValueInst);
                }

                ilProc.InsertBefore(insertBefore, Instruction.Create(newField.isStatic ? OpCodes.Stsfld : OpCodes.Stfld, ceNewField));
            }
        }