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