public NamedInstructionBlockChain CreateMethodExecutionArgsInstance(NamedInstructionBlockChain argumentsArrayChain)
        {
            // instance value
            var instanceVariable        = _creator.CreateVariable(_method.DeclaringType);
            var createThisVariableBlock = _creator.CreateThisVariable(instanceVariable, _method.DeclaringType);

            // MethodExecutionArgs instance
            var onEntryMethodTypeRef =
                _aspectTypeDefinition.Resolve().BaseType.Resolve().Methods.Single(x => x.Name == "OnEntry");
            var firstParameterType                = onEntryMethodTypeRef.Parameters.Single().ParameterType;
            var methodExecutionArgsTypeRef        = _moduleDefinition.ImportReference(firstParameterType);
            var methodExecutionArgsVariable       = _creator.CreateVariable(methodExecutionArgsTypeRef);
            var newObjectMethodExecutionArgsBlock = _creator.NewObject(
                methodExecutionArgsVariable,
                methodExecutionArgsTypeRef,
                _moduleDefinition,
                _aspectCounter);

            InstructionBlock callSetInstanceBlock = null;

            if (!_method.IsStatic)
            {
                var methodExecutionArgsSetInstanceMethodRef =
                    _referenceFinder.GetMethodReference(methodExecutionArgsTypeRef, md => md.Name == "set_Instance");
                callSetInstanceBlock = _creator.CallVoidInstanceMethod(methodExecutionArgsVariable,
                                                                       methodExecutionArgsSetInstanceMethodRef, instanceVariable);
            }

            var methodExecutionArgsSetArgumentsMethodRef =
                _referenceFinder.GetMethodReference(methodExecutionArgsTypeRef, md => md.Name == "set_Arguments");
            var callSetArgumentsBlock = _creator.CallVoidInstanceMethod(methodExecutionArgsVariable,
                                                                        methodExecutionArgsSetArgumentsMethodRef, argumentsArrayChain.Variable);

            var methodBaseTypeRef          = _referenceFinder.GetTypeReference(typeof(MethodBase));
            var methodBaseVariable         = _creator.CreateVariable(methodBaseTypeRef);
            var methodBaseGetCurrentMethod = _referenceFinder.GetMethodReference(methodBaseTypeRef,
                                                                                 md => md.Name == "GetCurrentMethod");
            var callGetCurrentMethodBlock = _creator.CallStaticMethod(methodBaseGetCurrentMethod, methodBaseVariable);

            var methodExecutionArgsSetMethodBaseMethodRef =
                _referenceFinder.GetMethodReference(methodExecutionArgsTypeRef, md => md.Name == "set_Method");
            var callSetMethodBlock = _creator.CallVoidInstanceMethod(methodExecutionArgsVariable,
                                                                     methodExecutionArgsSetMethodBaseMethodRef, methodBaseVariable);

            var newMethodExectionArgsBlockChain = new NamedInstructionBlockChain(methodExecutionArgsVariable,
                                                                                 methodExecutionArgsTypeRef);

            newMethodExectionArgsBlockChain.Add(newObjectMethodExecutionArgsBlock);
            newMethodExectionArgsBlockChain.Add(callSetArgumentsBlock);
            newMethodExectionArgsBlockChain.Add(callGetCurrentMethodBlock);
            newMethodExectionArgsBlockChain.Add(callSetMethodBlock);
            if (callSetInstanceBlock != null)
            {
                newMethodExectionArgsBlockChain.Add(createThisVariableBlock);
                newMethodExectionArgsBlockChain.Add(callSetInstanceBlock);
            }

            return(newMethodExectionArgsBlockChain);
        }
        public InstructionBlock NewObject(
            VariableDefinition newInstance,
            TypeReference instanceTypeReference,
            ModuleDefinition module,
            CustomAttribute aspect)
        {
            var typeDefinition = instanceTypeReference.Resolve();
            var constructor    = typeDefinition
                                 .Methods
                                 .SingleOrDefault(x => x.IsConstructor &&
                                                  !x.IsStatic &&
                                                  x.Parameters.Select(p => p.ParameterType.FullName)
                                                  .SequenceEqual(aspect?.ConstructorArguments.Select(a => a.Type.FullName) ?? new string[0]));

            if (constructor == null)
            {
                throw new InvalidOperationException(string.Format("Didn't find matching constructor on type '{0}'",
                                                                  typeDefinition.FullName));
            }

            var ctorRef = module.ImportReference(constructor);
            var newObjectInstruction        = _processor.Create(OpCodes.Newobj, ctorRef);
            var assignToVariableInstruction = _processor.Create(OpCodes.Stloc, newInstance);

            var loadConstValuesOnStack     = new List <Instruction>();
            var loadSetConstValuesToAspect = new List <Instruction>();

            if (aspect != null)
            {
                // ctor parameters
                var loadInstructions = aspect.Constructor.Parameters
                                       .Zip(aspect.ConstructorArguments, (p, v) => new { Parameter = p, Value = v })
                                       .SelectMany(x => LoadValueOnStack(x.Parameter.ParameterType, x.Value.Value))
                                       .ToList();
                loadConstValuesOnStack.AddRange(loadInstructions);

                // named arguments
                foreach (var property in aspect.Properties)
                {
                    var propertyCopy = property;
                    var propertyType = module.ImportReference(propertyCopy.Argument.Type.Resolve());

                    var loadOnStackInstruction         = LoadValueOnStack(propertyType, propertyCopy.Argument.Value);
                    var valueVariable                  = CreateVariable(propertyType);
                    var assignVariableInstructionBlock = AssignValueFromStack(valueVariable);

                    var methodRef = _referenceFinder.GetMethodReference(instanceTypeReference, md => md.Name == "set_" + propertyCopy.Name);
                    var setPropertyInstructionBlock = CallVoidInstanceMethod(methodRef,
                                                                             new VariablePersistable(newInstance),
                                                                             new VariablePersistable(valueVariable));

                    loadSetConstValuesToAspect.AddRange(loadOnStackInstruction);
                    loadSetConstValuesToAspect.AddRange(assignVariableInstructionBlock.Instructions);
                    loadSetConstValuesToAspect.AddRange(setPropertyInstructionBlock.Instructions);
                }

                foreach (var field in aspect.Fields)
                {
                    var fieldCopy = field;

                    var loadInstanceOnStackInstruction = _processor.Create(OpCodes.Ldloc, newInstance);
                    var loadOnStackInstruction         = LoadValueOnStack(fieldCopy.Argument.Type, fieldCopy.Argument.Value);

                    var fieldRef = instanceTypeReference.Resolve().Fields.First(f => f.Name == fieldCopy.Name);
                    var loadFieldInstructionBlock = _processor.Create(OpCodes.Stfld, fieldRef);

                    loadSetConstValuesToAspect.Add(loadInstanceOnStackInstruction);
                    loadSetConstValuesToAspect.AddRange(loadOnStackInstruction);
                    loadSetConstValuesToAspect.Add(loadFieldInstructionBlock);
                }
            }

            var allInstructions = new List <Instruction>();

            allInstructions.AddRange(loadConstValuesOnStack);
            allInstructions.Add(newObjectInstruction);
            allInstructions.Add(assignToVariableInstruction);
            allInstructions.AddRange(loadSetConstValuesToAspect);

            return(new InstructionBlock(
                       "NewObject: " + instanceTypeReference.Name,
                       allInstructions));
        }
        public InstructionBlock NewObject(
            VariableDefinition newInstance,
            TypeReference instanceTypeReference,
            ModuleDefinition module,
            CustomAttribute aspect,
            int aspectCounter)
        {
            var typeDefinition = instanceTypeReference.Resolve();
            var constructor    = typeDefinition.Methods
                                 .Where(x => x.IsConstructor)
                                 .Where(x => !x.IsStatic)
                                 .SingleOrDefault(x => x.Parameters.Count == (aspect == null ? 0 : aspect.Constructor.Parameters.Count));

            if (constructor == null)
            {
                throw new InvalidOperationException(string.Format("Didn't found matching constructor on type '{0}'",
                                                                  typeDefinition.FullName));
            }

            var ctorRef = module.Import(constructor);
            var newObjectInstruction        = _processor.Create(OpCodes.Newobj, ctorRef);
            var assignToVariableInstruction = _processor.Create(OpCodes.Stloc, newInstance);

            var loadConstValuesOnStack     = new List <Instruction>();
            var loadSetConstValuesToAspect = new List <Instruction>();

            if (aspect != null)
            {
                // ctor parameters
                var loadInstructions = aspect.Constructor.Parameters
                                       .Zip(aspect.ConstructorArguments, (p, v) => new { Parameter = p, Value = v })
                                       .SelectMany(x => LoadValueOnStack(x.Parameter.ParameterType, x.Value.Value, module))
                                       .ToList();
                loadConstValuesOnStack.AddRange(loadInstructions);

                // named arguments
                int namedArgumentCounter = 0;
                foreach (var property in aspect.Properties)
                {
                    var propertyCopy = property;

                    var loadOnStackInstruction         = LoadValueOnStack(propertyCopy.Argument.Type, propertyCopy.Argument.Value, module);
                    var valueVariable                  = CreateVariable(propertyCopy.Argument.Type);
                    var assignVariableInstructionBlock = AssignValueFromStack(valueVariable);

                    var methodRef = _referenceFinder.GetMethodReference(instanceTypeReference, md => md.Name == "set_" + propertyCopy.Name);
                    var setPropertyInstructionBlock = CallVoidInstanceMethod(newInstance, methodRef, valueVariable);

                    loadSetConstValuesToAspect.AddRange(loadOnStackInstruction);
                    loadSetConstValuesToAspect.AddRange(assignVariableInstructionBlock.Instructions);
                    loadSetConstValuesToAspect.AddRange(setPropertyInstructionBlock.Instructions);

                    namedArgumentCounter++;
                }
            }

            var allInstructions = new List <Instruction>();

            allInstructions.AddRange(loadConstValuesOnStack);
            allInstructions.Add(newObjectInstruction);
            allInstructions.Add(assignToVariableInstruction);
            allInstructions.AddRange(loadSetConstValuesToAspect);

            return(new InstructionBlock(
                       "NewObject: " + instanceTypeReference.Name,
                       allInstructions));
        }