public static void AddLazyLoadingToReferencingMethods(this NavigationPropertyWeavingContext context)
        {
            IEnumerable <MethodDefinition> getterAndSetterMethods = context.ClassWeavingContext.TypeDefinition.Properties
                                                                    .Where(propertyDefinition => propertyDefinition != context.PropertyDefinition)
                                                                    .SelectMany(propertyDefinition => new[] { propertyDefinition.SetMethod, propertyDefinition.GetMethod })
                                                                    .Where(methodDefinition => methodDefinition != null &&
                                                                           methodDefinition.Body.Instructions.Any(body => body.Operand == context.FieldDefinition));

            IEnumerable <MethodDefinition> methods = context.ClassWeavingContext.TypeDefinition.Methods.Where(methodDefinition =>
                                                                                                              !methodDefinition.IsSpecialName && !methodDefinition.IsGetter && !methodDefinition.IsSetter &&
                                                                                                              !methodDefinition.IsConstructor && methodDefinition.Body.Instructions.Any(x => x.Operand == context.FieldDefinition));

            foreach (MethodDefinition methodDefinition in getterAndSetterMethods.Union(methods))
            {
                context.WriteDebug($"Add lazy loading to method {context.ClassWeavingContext.TypeDefinition.Name}:{methodDefinition.Name}");

                ILProcessorContext processor = methodDefinition.Body.GetILProcessor().Start();

                var loadInstructionStart = processor.Prepend(x => x.Create(OpCodes.Ldarg_0));

                var loadInstructionEnd = loadInstructionStart.Append(x => x.Create(OpCodes.Ldstr, context.PropertyDefinition.Name))
                                         .Append(x => x.Create(OpCodes.Callvirt, context.ClassWeavingContext.References.LazyLoaderInvokeMethod));

                loadInstructionStart.Prepend(x => x.Create(OpCodes.Ldarg_0))
                .Append(x => x.Create(OpCodes.Ldfld, context.ClassWeavingContext.LazyLoaderField))
                .Append(x => x.Create(OpCodes.Dup))
                .Append(x => x.Create(OpCodes.Brtrue_S, loadInstructionStart.CurrentInstruction))
                .Append(x => x.Create(OpCodes.Pop))
                .Append(x => x.Create(OpCodes.Br_S, loadInstructionEnd.CurrentInstruction !.Next));
            }
        }
        public static void AddConstructorOverloads(this ClassWeavingContext context)
        {
            foreach (MethodDefinition constructor in context.TypeDefinition.GetConstructors().ToList())
            {
                context.WriteDebug(
                    $"Add constructor overload for {context.TypeDefinition.Name}({string.Join(", ", constructor.Parameters.Select(x => $"{x.ParameterType.Name} {x.Name}"))})");

                MethodDefinition method = new MethodDefinition(constructor.Name, constructor.Attributes,
                                                               context.TypeDefinition.Module.TypeSystem.Void)
                {
                    IsFamily = true,
                };

                foreach (ParameterDefinition parameterDefinition in constructor.Parameters)
                {
                    method.Parameters.Add(new ParameterDefinition(parameterDefinition.Name, parameterDefinition.Attributes,
                                                                  parameterDefinition.ParameterType));
                }

                ParameterDefinition lazyLoaderParameter =
                    new ParameterDefinition("lazyLoader", ParameterAttributes.None, context.References.LazyLoaderType);
                method.Parameters.Add(lazyLoaderParameter);

                context.TypeDefinition.Methods.Add(method);

                ILProcessorContext processor = method.Body.GetILProcessor().Start();

                processor = processor.Append(x => x.Create(OpCodes.Ldarg_0));

                foreach (ParameterDefinition parameterDefinition in constructor.Parameters)
                {
                    processor = processor.Append(x => x.Create(OpCodes.Ldarg, parameterDefinition.Index + 1));
                }

                processor = processor.Append(x => x.Create(OpCodes.Call, constructor));

                processor = processor.Append(x => x.Create(OpCodes.Ldarg_0))
                            .Append(x => x.Create(OpCodes.Ldarg, lazyLoaderParameter))
                            .Append(x => x.Create(OpCodes.Stfld, context.LazyLoaderField))
                            .Append(x => x.Create(OpCodes.Ret));
            }
        }