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); } }