private void ProcessExtensionMethodCalls(MethodDefinition method, AutoPropertyToBackingFieldMap autoPropertyToBackingFieldMap)
        {
            var processor = new ExtensionMethodProcessor(_logger, _symbolReader, method, autoPropertyToBackingFieldMap);

            processor.ProcessExtensionMethodCalls("SetBackingField", pi => Instruction.Create(OpCodes.Stfld, pi.BackingField));
            processor.ProcessExtensionMethodCalls("SetProperty", pi => Instruction.Create(OpCodes.Call, pi.Property.SetMethod));
        }
        private void BypassAutoPropertySetters([NotNull] MethodDefinition method, [NotNull] AutoPropertyToBackingFieldMap autoPropertyToBackingFieldMap)
        {
            // ReSharper disable once PossibleNullReferenceException
            var instructions = method.Body.Instructions;

            // ReSharper disable once PossibleNullReferenceException
            for (var index = 0; index < instructions.Count; index++)
            {
                var instruction = instructions[index];

                // ReSharper disable once AssignNullToNotNullAttribute
                if (!instruction.IsPropertySetterCall(out string propertyName))
                {
                    continue;
                }

                if (!autoPropertyToBackingFieldMap.TryGetValue(propertyName, out var propertyInfo))
                {
                    continue;
                }

                _logger.LogInfo($"Replace setter of property {propertyName} in method {method.FullName} with backing field assignment.");

                instructions[index] = Instruction.Create(OpCodes.Stfld, propertyInfo.BackingField);
            }
        }
            public ExtensionMethodProcessor(ILogger logger, ISymbolReader?symbolReader, MethodDefinition method, AutoPropertyToBackingFieldMap autoPropertyToBackingFieldMap)
            {
                _logger = logger;
                _method = method;
                _autoPropertyToBackingFieldMap = autoPropertyToBackingFieldMap;

                _instructionSequences = new InstructionSequences(method.Body.Instructions, method.ReadSequencePoints(symbolReader));
            }
        private void ProcessExtensionMethodCalls([NotNull] MethodDefinition method, [NotNull] AutoPropertyToBackingFieldMap autoPropertyToBackingFieldMap)
        {
            var processor = new ExtensionMethodProcessor(_logger, _symbolReader, method, autoPropertyToBackingFieldMap);

            // ReSharper disable PossibleNullReferenceException
            processor.ProcessExtensionMethodCalls("SetBackingField", pi => Instruction.Create(OpCodes.Stfld, pi.BackingField));
            processor.ProcessExtensionMethodCalls("SetProperty", pi => Instruction.Create(OpCodes.Call, pi.Property.SetMethod));
            // ReSharper restore PossibleNullReferenceException
        }
            public ExtensionMethodProcessor([NotNull] ILogger logger, [CanBeNull] ISymbolReader symbolReader, [NotNull] MethodDefinition method, [NotNull] AutoPropertyToBackingFieldMap autoPropertyToBackingFieldMap)
            {
                _logger = logger;
                _method = method;
                _autoPropertyToBackingFieldMap = autoPropertyToBackingFieldMap;

                Debug.Assert(method.Body?.Instructions != null, "method.Body.Instructions != null");

                _instructionSequences = new InstructionSequences(method.Body.Instructions, method.ReadSequencePoints(symbolReader));
            }
        internal void Execute()
        {
            var allTypes = _moduleDefinition.GetTypes();

            // ReSharper disable once AssignNullToNotNullAttribute
            var allClasses = allTypes
                             .Where(x => x != null && x.IsClass && (x.BaseType != null));

            try
            {
                foreach (var classDefinition in allClasses)
                {
                    var shouldBypassAutoPropertySetters = classDefinition.ShouldBypassAutoPropertySettersInConstructors()
                                                          ?? _moduleDefinition.Assembly.ShouldBypassAutoPropertySettersInConstructors()
                                                          ?? false;

                    var autoPropertyToBackingFieldMap = new AutoPropertyToBackingFieldMap(classDefinition);

                    // ReSharper disable once AssignNullToNotNullAttribute
                    // ReSharper disable once PossibleNullReferenceException
                    var allMethods = classDefinition.Methods.Where(method => method.HasBody);

                    foreach (var method in allMethods)
                    {
                        if (method.IsConstructor && shouldBypassAutoPropertySetters)
                        {
                            BypassAutoPropertySetters(method, autoPropertyToBackingFieldMap);
                        }

                        ProcessExtensionMethodCalls(method, autoPropertyToBackingFieldMap);
                    }
                }
            }
            catch (Exception ex)
            {
                _logger.LogError("Unhandled exception. Weaving aborted. The most probable reason is that the module has no or incompatible debug information (.pdb)");
                _logger.LogDebug(ex.ToString());
            }
        }
        private void BypassAutoPropertySetters(MethodDefinition method, AutoPropertyToBackingFieldMap autoPropertyToBackingFieldMap)
        {
            var instructions = method.Body.Instructions;

            for (var index = 0; index < instructions.Count; index++)
            {
                var instruction = instructions[index];

                if (!instruction.IsPropertySetterCall(out string?propertyName) || propertyName == null)
                {
                    continue;
                }

                if (!autoPropertyToBackingFieldMap.TryGetValue(propertyName, out var propertyInfo))
                {
                    continue;
                }

                _logger.LogInfo($"Replace setter of property {propertyName} in method {method.FullName} with backing field assignment.");

                instructions[index] = Instruction.Create(OpCodes.Stfld, propertyInfo.BackingField);
            }
        }