public static Create ( Mono.Cecil.Cil.OpCode opcode ) : |
||
opcode | Mono.Cecil.Cil.OpCode | |
Résultat |
private void InsertAndBoxConstant(Injector injector, object constant, TypeReference type, TypeReference boxType = null) { if (type.IsType <string>()) { injector.Insert(OpCodes.Ldstr, (string)constant); } else if (type.IsType <int>()) { injector.Insert(OpCodes.Ldc_I4, (int)constant); } else if (type.IsType <long>()) { injector.Insert(OpCodes.Ldc_I8, (long)constant); } else if (type.IsType <double>()) { injector.Insert(OpCodes.Ldc_R8, (double)constant); } else if (type.IsType <float>()) { injector.Insert(OpCodes.Ldc_R4, (float)constant); } else if (type.IsType <short>()) { injector.Insert(OpCodes.Ldc_I4, (short)constant); } else if (type.IsType <byte>()) { injector.Insert(OpCodes.Ldc_I4, (byte)constant); } else if (type.IsType <uint>()) { injector.Insert(OpCodes.Ldc_I4, (int)(uint)constant); } else if (type.IsType <ulong>()) { injector.Insert(OpCodes.Ldc_I8, (long)(ulong)constant); } else if (type.IsType <ushort>()) { injector.Insert(OpCodes.Ldc_I4, (ushort)constant); } else if (type.IsType <sbyte>()) { injector.Insert(OpCodes.Ldc_I4, (sbyte)constant); } if (boxType != null) { injector.Insert(Instruction.Create(OpCodes.Box, boxType)); } Logger.Warning($"Unknown constant type {constant.GetType().FullName}"); }
public Instruction Create(OpCode opcode, int value) { if (opcode.OperandType == OperandType.InlineVar) { return(Instruction.Create(opcode, body.Variables [value])); } if (opcode.OperandType == OperandType.InlineArg) { return(Instruction.Create(opcode, body.GetParameter(value))); } return(Instruction.Create(opcode, value)); }
private void ProcessMethod(TypeDefinition type, MethodDefinition method, ICodeGenerator generator) { List <ParameterDefinition> dependencyParameters = method.Parameters.Where( p => p.CustomAttributes.Any(a => a.AttributeType.IsType(Import.AutoDI.DependencyAttributeType))).ToList(); List <PropertyDefinition> dependencyProperties = method.IsConstructor ? type.Properties.Where(p => p.CustomAttributes.Any(a => a.AttributeType.IsType(Import.AutoDI.DependencyAttributeType))).ToList() : new List <PropertyDefinition>(); if (dependencyParameters.Any() || dependencyProperties.Any()) { Logger.Debug($"Processing method '{method.Name}' for '{method.DeclaringType.FullName}'", DebugLogLevel.Verbose); var injector = new Injector(method); IMethodGenerator methodGenerator = generator?.Method(method); foreach (ParameterDefinition parameter in dependencyParameters) { if (!parameter.IsOptional) { Logger.Info( $"Constructor parameter {parameter.ParameterType.Name} {parameter.Name} is marked with {Import.AutoDI.DependencyAttributeType.FullName} but is not an optional parameter. In {type.FullName}."); } if (parameter.Constant != null) { Logger.Warning( $"Constructor parameter {parameter.ParameterType.Name} {parameter.Name} in {type.FullName} does not have a null default value. AutoDI will only resolve dependencies that are null"); } var initInstruction = Instruction.Create(OpCodes.Ldarg, parameter); var storeInstruction = Instruction.Create(OpCodes.Starg, parameter); ResolveDependency(parameter.ParameterType, parameter, new[] { initInstruction }, null, storeInstruction, parameter.Name); } foreach (PropertyDefinition property in dependencyProperties) { FieldDefinition backingField = null; //Store the return from the resolve method in the method parameter if (property.SetMethod == null) { //NB: Constant string, compiler detail... yuck yuck and double duck backingField = property.DeclaringType.Fields.FirstOrDefault(f => f.Name == $"<{property.Name}>k__BackingField"); if (backingField == null) { Logger.Warning( $"{property.FullName} is marked with {Import.AutoDI.DependencyAttributeType.FullName} but cannot be set. Dependency properties must either be auto properties or have a setter"); continue; } } //injector.Insert(OpCodes.Call, property.GetMethod); ResolveDependency(property.PropertyType, property, new[] { Instruction.Create(OpCodes.Ldarg_0), Instruction.Create(OpCodes.Call, property.GetMethod), }, Instruction.Create(OpCodes.Ldarg_0), property.SetMethod != null ? Instruction.Create(OpCodes.Call, property.SetMethod) : Instruction.Create(OpCodes.Stfld, backingField), property.Name); } methodGenerator?.Append("//We now return you to your regularly scheduled method"); method.Body.OptimizeMacros(); void ResolveDependency(TypeReference dependencyType, ICustomAttributeProvider source, Instruction[] loadSource, Instruction resolveAssignmentTarget, Instruction setResult, string dependencyName) { //Push dependency parameter onto the stack if (methodGenerator != null) { methodGenerator.Append($"if ({dependencyName} == null)", loadSource.First()); methodGenerator.Append(Environment.NewLine + "{" + Environment.NewLine); } injector.Insert(loadSource); var afterParam = Instruction.Create(OpCodes.Nop); //Push null onto the stack injector.Insert(OpCodes.Ldnull); //Push 1 if the values are equal, 0 if they are not equal injector.Insert(OpCodes.Ceq); //Branch if the value is false (0), the dependency was set by the caller we wont replace it injector.Insert(OpCodes.Brfalse_S, afterParam); //Push the dependency resolver onto the stack if (resolveAssignmentTarget != null) { injector.Insert(resolveAssignmentTarget); } //Create parameters array var dependencyAttribute = source.CustomAttributes.First(x => x.AttributeType.IsType(Import.AutoDI.DependencyAttributeType)); var values = (dependencyAttribute.ConstructorArguments?.FirstOrDefault().Value as CustomAttributeArgument[]) ?.Select(x => x.Value) .OfType <CustomAttributeArgument>() .ToArray(); //Create array of appropriate length Instruction loadArraySize = injector.Insert(OpCodes.Ldc_I4, values?.Length ?? 0); if (methodGenerator != null) { methodGenerator.Append($" {dependencyName} = GlobalDI.GetService<{dependencyType.FullNameCSharp()}>();", resolveAssignmentTarget ?? loadArraySize); methodGenerator.Append(Environment.NewLine); } injector.Insert(OpCodes.Newarr, ModuleDefinition.ImportReference(typeof(object))); if (values?.Length > 0) { for (int i = 0; i < values.Length; ++i) { injector.Insert(OpCodes.Dup); //Push the array index to insert injector.Insert(OpCodes.Ldc_I4, i); //Insert constant value with any boxing/conversion needed InsertObjectConstant(injector, values[i].Value, values[i].Type.Resolve()); //Push the object into the array at index injector.Insert(OpCodes.Stelem_Ref); } } //Call the resolve method var getServiceMethod = new GenericInstanceMethod(Import.AutoDI.GlobalDI.GetService) { GenericArguments = { ModuleDefinition.ImportReference(dependencyType) } }; injector.Insert(OpCodes.Call, getServiceMethod); //Set the return from the resolve method into the parameter injector.Insert(setResult); injector.Insert(afterParam); if (methodGenerator != null) { methodGenerator.Append("}", afterParam); methodGenerator.Append(Environment.NewLine); } } } }
public Instruction Create(OpCode opcode, sbyte value) { return(Instruction.Create(opcode, value)); }
public Instruction Create(OpCode opcode, MethodReference method) { return(Instruction.Create(opcode, method)); }
public Instruction Create(OpCode opcode, FieldReference field) { return(Instruction.Create(opcode, field)); }
public Instruction Create(OpCode opcode, TypeReference type) { return(Instruction.Create(opcode, type)); }
public Instruction Create(OpCode opcode, CallSite site) { return(Instruction.Create(opcode, site)); }
public Instruction Create(OpCode opcode) { return(Instruction.Create(opcode)); }
public Instruction Create(OpCode opcode, ParameterDefinition parameter) { return(Instruction.Create(opcode, parameter)); }
public Instruction Create(OpCode opcode, VariableDefinition variable) { return(Instruction.Create(opcode, variable)); }
public Instruction Create(OpCode opcode, Instruction [] targets) { return(Instruction.Create(opcode, targets)); }
internal static void EncapsulateMethodBodyWithTryFinallyBlock(this ILProcessor ilProcessor, Instruction firstInstruction, Action <ILProcessor, Instruction> insertBeforReturn) { var body = ilProcessor.Body; if (body.Method.IsConstructor && !body.Method.IsStatic) { var ctor = GetFirstConstructorInstruction(body); if (ctor != null) { if (body.Instructions.IndexOf(ctor) > 2) { var lastInstruction = body.Instructions.Last(); var firtLDarg0BeforeCtor = ctor.GetFirstPreviousLdarg_0(); if (firstInstruction != firtLDarg0BeforeCtor) { EncapsulateWithTryCatch(ilProcessor, firstInstruction, firtLDarg0BeforeCtor); } if (ctor.GetFirstNotNopInstruction().Equals(lastInstruction)) { insertBeforReturn(ilProcessor, lastInstruction); return; } } if (firstInstruction.Next.OpCode != OpCodes.Nop) { firstInstruction = Instruction.Create(OpCodes.Nop); ilProcessor.InsertAfter(ctor, firstInstruction); } } } var returnStart = ilProcessor.FixReturns(); var beforeReturn = Instruction.Create(OpCodes.Endfinally); ilProcessor.InsertBefore(returnStart, beforeReturn); if (body.Instructions.First().Equals(firstInstruction)) { Instruction tryStart = Instruction.Create(OpCodes.Nop); ilProcessor.InsertBefore(firstInstruction, tryStart); } Instruction finallyStart = Instruction.Create(OpCodes.Nop); ilProcessor.InsertBefore(beforeReturn, finallyStart); insertBeforReturn(ilProcessor, beforeReturn); var handler = new ExceptionHandler(ExceptionHandlerType.Finally) { TryStart = firstInstruction, TryEnd = finallyStart, HandlerStart = finallyStart, HandlerEnd = returnStart, }; body.ExceptionHandlers.Add(handler); }