public HookPropertySetResult HookPropertySet(GenerateEventResult generateEventResult, string addToType, string propertyName) { var addEventToType = _module.Types.Single(t => t.Name == addToType); if (addEventToType.Events.Any(ev => ev.Name == generateEventResult.EventDefinition.Name)) { return(new HookPropertySetResult($"'{generateEventResult.EventDefinition.FullName}' already existing in type '{addToType}', skipping...")); } addEventToType.Fields.Add(generateEventResult.FieldDefinition); addEventToType.Methods.Add(generateEventResult.EventDefinition.AddMethod); addEventToType.Methods.Add(generateEventResult.EventDefinition.RemoveMethod); addEventToType.Events.Add(generateEventResult.EventDefinition); System.Console.WriteLine($"Added event: {generateEventResult.EventDefinition.Name} to '{addEventToType.Name}'"); InjectEventCallAtPropertySetterStart(propertyName, addEventToType, generateEventResult); System.Console.WriteLine($"Event: {generateEventResult.EventDefinition.Name} will be called on start property-setter '{addEventToType.Name}:{propertyName}'"); return(new HookPropertySetResult(null)); }
private void InjectEventCallAtPropertySetterStart(string propertyName, TypeDefinition addEventToType, GenerateEventResult generateEventResult) { //change existing method to call into event var setMethod = addEventToType.Methods.Single(m => m.Name == $"set_{propertyName}"); var il = setMethod.Body.GetILProcessor(); var firstInstruction = setMethod.Body.Instructions.First(); var loadThisArgForEventCall = il.Create(OpCodes.Ldarg_0); il.InsertBefore(firstInstruction, il.Create(OpCodes.Ldarg_0)); il.InsertBefore(firstInstruction, il.Create(OpCodes.Ldfld, generateEventResult.FieldDefinition)); il.InsertBefore(firstInstruction, il.Create(OpCodes.Dup)); il.InsertBefore(firstInstruction, il.Create(OpCodes.Brtrue, loadThisArgForEventCall)); il.InsertBefore(firstInstruction, il.Create(OpCodes.Pop)); il.InsertBefore(firstInstruction, il.Create(OpCodes.Br, firstInstruction)); il.InsertBefore(firstInstruction, loadThisArgForEventCall); il.InsertBefore(firstInstruction, il.Create(OpCodes.Ldarg_1)); var genericInvoke = CreateGenericInvokeMethodReference(generateEventResult.GenericHandlerParamType, generateEventResult.FieldDefinition); il.InsertBefore(firstInstruction, il.Create(OpCodes.Callvirt, genericInvoke)); }