Create() public static method

public static Create ( Mono.Cecil.Cil.OpCode opcode ) : Instruction
opcode Mono.Cecil.Cil.OpCode
return Instruction
コード例 #1
0
ファイル: ModuleWeaver.cs プロジェクト: izaruba/AutoDI
 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}");
 }
コード例 #2
0
ファイル: ILProcessor.cs プロジェクト: tris2481/ILSpy
        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));
        }
コード例 #3
0
ファイル: ModuleWeaver.cs プロジェクト: izaruba/AutoDI
    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);
                }
            }
        }
    }
コード例 #4
0
ファイル: ILProcessor.cs プロジェクト: tris2481/ILSpy
 public Instruction Create(OpCode opcode, sbyte value)
 {
     return(Instruction.Create(opcode, value));
 }
コード例 #5
0
ファイル: ILProcessor.cs プロジェクト: tris2481/ILSpy
 public Instruction Create(OpCode opcode, MethodReference method)
 {
     return(Instruction.Create(opcode, method));
 }
コード例 #6
0
ファイル: ILProcessor.cs プロジェクト: tris2481/ILSpy
 public Instruction Create(OpCode opcode, FieldReference field)
 {
     return(Instruction.Create(opcode, field));
 }
コード例 #7
0
ファイル: ILProcessor.cs プロジェクト: tris2481/ILSpy
 public Instruction Create(OpCode opcode, TypeReference type)
 {
     return(Instruction.Create(opcode, type));
 }
コード例 #8
0
ファイル: ILProcessor.cs プロジェクト: tris2481/ILSpy
 public Instruction Create(OpCode opcode, CallSite site)
 {
     return(Instruction.Create(opcode, site));
 }
コード例 #9
0
ファイル: ILProcessor.cs プロジェクト: tris2481/ILSpy
 public Instruction Create(OpCode opcode)
 {
     return(Instruction.Create(opcode));
 }
コード例 #10
0
ファイル: ILProcessor.cs プロジェクト: tris2481/ILSpy
 public Instruction Create(OpCode opcode, ParameterDefinition parameter)
 {
     return(Instruction.Create(opcode, parameter));
 }
コード例 #11
0
ファイル: ILProcessor.cs プロジェクト: tris2481/ILSpy
 public Instruction Create(OpCode opcode, VariableDefinition variable)
 {
     return(Instruction.Create(opcode, variable));
 }
コード例 #12
0
ファイル: ILProcessor.cs プロジェクト: tris2481/ILSpy
 public Instruction Create(OpCode opcode, Instruction [] targets)
 {
     return(Instruction.Create(opcode, targets));
 }
コード例 #13
0
        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);
        }