Catel.Fody.Weaving.AutoProperties.OnPropertyChangedWeaver.AddOrUpdateOnPropertyChangedMethod C# (CSharp) Method

AddOrUpdateOnPropertyChangedMethod() private method

private AddOrUpdateOnPropertyChangedMethod ( Mono.Cecil.PropertyDefinition property ) : bool
property Mono.Cecil.PropertyDefinition
return bool
        private bool AddOrUpdateOnPropertyChangedMethod(PropertyDefinition property)
        {
            var getMethodReference = _catelType.TypeDefinition.Module.Import(_catelType.AdvancedPropertyChangedEventArgsType.GetProperty("PropertyName").Resolve().GetMethod);
            var stringEqualsMethodReference = _catelType.TypeDefinition.Module.Import(GetSystemObjectEqualsMethodReference(_catelType.TypeDefinition.Module));

            var dependentProperties = _catelType.GetDependentPropertiesFrom(property).ToList();
            if (dependentProperties.Count > 0)
            {
                var onPropertyChangedMethod = EnsureOnPropertyChangedMethod();
                if (onPropertyChangedMethod == null)
                {
                    FodyEnvironment.LogWarning($"No call to base.OnPropertyChanged(e) or a custom implementation in '{property.DeclaringType.Name}', cannot weave this method to automatically raise on dependent property change notifications");
                    return false;
                }

                var idx = onPropertyChangedMethod.Body.Instructions.ToList().FindLastIndex(instruction => instruction.OpCode == OpCodes.Ret);
                if (idx > -1)
                {
                    var booleanTypeReference = _catelType.TypeDefinition.Module.Import(_msCoreReferenceFinder.GetCoreTypeReference("Boolean"));
                    if (onPropertyChangedMethod.Body.Variables.ToList().FirstOrDefault(definition => definition.VariableType != booleanTypeReference) == null)
                    {
                        onPropertyChangedMethod.Body.Variables.Add(new VariableDefinition(booleanTypeReference));
                        onPropertyChangedMethod.Body.InitLocals = true;
                    }

                    foreach (var propertyDefinition in dependentProperties)
                    {
                        onPropertyChangedMethod.Body.Instructions.Insert(idx++, Instruction.Create(OpCodes.Ldarg_1));
                        onPropertyChangedMethod.Body.Instructions.Insert(idx++, Instruction.Create(OpCodes.Callvirt, getMethodReference));
                        onPropertyChangedMethod.Body.Instructions.Insert(idx++, Instruction.Create(OpCodes.Ldstr, property.Name));
                        onPropertyChangedMethod.Body.Instructions.Insert(idx++, Instruction.Create(OpCodes.Callvirt, stringEqualsMethodReference));
                        onPropertyChangedMethod.Body.Instructions.Insert(idx++, Instruction.Create(OpCodes.Ldc_I4_0));
                        onPropertyChangedMethod.Body.Instructions.Insert(idx++, Instruction.Create(OpCodes.Ceq));
                        onPropertyChangedMethod.Body.Instructions.Insert(idx++, Instruction.Create(OpCodes.Stloc_0));
                        onPropertyChangedMethod.Body.Instructions.Insert(idx++, Instruction.Create(OpCodes.Ldloc_0));

                        var jmpIdx = idx++;
                        onPropertyChangedMethod.Body.Instructions.Insert(jmpIdx, Instruction.Create(OpCodes.Nop));

                        onPropertyChangedMethod.Body.Instructions.Insert(idx++, Instruction.Create(OpCodes.Nop));
                        onPropertyChangedMethod.Body.Instructions.Insert(idx++, Instruction.Create(OpCodes.Ldarg_0));
                        onPropertyChangedMethod.Body.Instructions.Insert(idx++, Instruction.Create(OpCodes.Ldstr, propertyDefinition.Name));
                        onPropertyChangedMethod.Body.Instructions.Insert(idx++, Instruction.Create(OpCodes.Call, _catelType.RaisePropertyChangedInvoker));
                        onPropertyChangedMethod.Body.Instructions.Insert(idx++, Instruction.Create(OpCodes.Nop));
                        onPropertyChangedMethod.Body.Instructions.Insert(idx++, Instruction.Create(OpCodes.Nop));

                        onPropertyChangedMethod.Body.Instructions[jmpIdx] = Instruction.Create(OpCodes.Brtrue_S, onPropertyChangedMethod.Body.Instructions[idx - 1]);
                    }
                }
            }

            return true;
        }