private IEnumerable<Instruction> GetCommandInitializationInstructions(CommandData commandData) { Instruction blockEnd = Instruction.Create(OpCodes.Nop); //// Null check //// if (Command == null) { ... } yield return Instruction.Create(OpCodes.Nop); yield return Instruction.Create(OpCodes.Ldarg_0); yield return Instruction.Create(OpCodes.Call, commandData.CommandProperty.GetMethod); yield return Instruction.Create(OpCodes.Ldnull); yield return Instruction.Create(OpCodes.Ceq); yield return Instruction.Create(OpCodes.Ldc_I4_0); yield return Instruction.Create(OpCodes.Ceq); yield return Instruction.Create(OpCodes.Stloc_0); yield return Instruction.Create(OpCodes.Ldloc_0); yield return Instruction.Create(OpCodes.Brtrue_S, blockEnd); foreach (var instruction in GetSetCommandInstructions(commandData)) { yield return instruction; } // BlockEnd is the end of the if (Command == null) {} block (i.e. think the closing brace) yield return blockEnd; }
internal IEnumerable<Instruction> GetSetCommandInstructions(CommandData command) { var commandConstructors = Assets.CommandImplementationConstructors; if (Assets.DelegateCommandImplementationWasInjected) { var delegateCommandType = Assets.ModuleDefinition.GetType(DelegateCommandClassInjectionProcessor.GeneratedCommandClassName); commandConstructors = commandConstructors.Concat(delegateCommandType.GetConstructors()).ToList(); } if (command.OnExecuteMethods.Count > 0) { MethodReference commandConstructor; var onExecuteMethod = command.OnExecuteMethods[0]; var canExecuteMethod = command.CanExecuteMethods.FirstOrDefault(); if (canExecuteMethod == null) { commandConstructor = commandConstructors.FirstOrDefault(mf=>mf.Parameters.Count == 1); commandConstructor = GetConstructorResolved(commandConstructor, onExecuteMethod); yield return Instruction.Create(OpCodes.Ldarg_0); yield return Instruction.Create(OpCodes.Ldarg_0); yield return Instruction.Create(OpCodes.Ldftn, onExecuteMethod); yield return Instruction.Create(OpCodes.Newobj, GetActionConstructorForExecuteMethod(onExecuteMethod, commandConstructor)); yield return Instruction.Create(OpCodes.Newobj, commandConstructor); yield return Instruction.Create(OpCodes.Call, command.CommandProperty.SetMethod); yield return Instruction.Create(OpCodes.Nop); yield return Instruction.Create(OpCodes.Nop); } else { commandConstructor = commandConstructors.OrderByDescending(mf => mf.Parameters.Count).First(); commandConstructor = GetConstructorResolved(commandConstructor, onExecuteMethod); yield return Instruction.Create(OpCodes.Nop); yield return Instruction.Create(OpCodes.Ldarg_0); yield return Instruction.Create(OpCodes.Ldarg_0); yield return Instruction.Create(OpCodes.Ldftn, command.OnExecuteMethods.Single()); yield return Instruction.Create(OpCodes.Newobj, GetActionConstructorForExecuteMethod(onExecuteMethod, commandConstructor)); yield return Instruction.Create(OpCodes.Ldarg_0); yield return Instruction.Create(OpCodes.Ldftn, command.CanExecuteMethods.Single()); yield return Instruction.Create(OpCodes.Newobj, GetPredicateConstructorForCanExecuteMethod(canExecuteMethod, commandConstructor)); yield return Instruction.Create(OpCodes.Newobj, commandConstructor); yield return Instruction.Create(OpCodes.Call, command.CommandProperty.SetMethod); yield return Instruction.Create(OpCodes.Nop); yield return Instruction.Create(OpCodes.Nop); } } }
public bool TryAddCommandPropertyInitialization(MethodDefinition initializeMethod, CommandData commandData) { if (!Assets.CommandImplementationConstructors.Any()) { if (!Assets.DelegateCommandImplementationWasInjected) { Assets.Log.Info("Skipped command initialization for command {0}, because there is no eligible command implementation to bind to.", commandData); return false; } } if (!initializeMethod.Body.Variables.Any(vDef => vDef.VariableType.IsBoolean() && vDef.Name == "isNull")) { var vDef = new VariableDefinition("isNull", Type.Module.TypeSystem.Boolean); initializeMethod.Body.Variables.Add(vDef); } var instructions = initializeMethod.Body.Instructions; GetOrCreateLastReturnInstruction(initializeMethod); var instructionsToAdd = GetCommandInitializationInstructions(commandData).ToArray(); instructions.Prepend(instructionsToAdd); commandData.CommandInitializationInjected = true; return true; }