/// <summary> /// Creates a new MemberImporter to import a type to destination, automatically adding any other required importer /// </summary> /// <param name="type"></param> /// <param name="destType"></param> /// <param name="importList"></param> /// <param name="options"></param> /// <returns></returns> public static MemberImporter CreateTypeImporter(TypeReference type, MemberImportingSession session, List <MemberImporter> importList, MemberImportingOptions options) { //Return value MemberImporter ret; //Checks if the type is a generic instance type or a generic parameter if (type is GenericParameter) { ret = MemberImporter.Create((_, __) => type); } else if (type is TypeSpecification) { ret = new TypeSpecificationImporter((TypeSpecification)type, session).Scan(options); } else { //Checks if the importer is in the dictionary MemberImporter importer; if (session.RegisteredImporters.TryGetValue(type, out importer)) { return(importer); } //Creates the importer, registers it and returns importer = Helpers.CreateTypeImporterForTypeDefinition(((TypeReference)type).Resolve(), session, importList, options); session.RegisteredImporters.Add(type, importer); importer.Scan(options); importList.Add(importer); return(importer); } //Adds the return value to the import list and returns importList.Add(ret); return(ret); }
protected override void ScanCore(MemberImportingOptions options, List <MemberImporter> importList) { //Type var type = (GenericInstanceType)Member; //Element type var elType = type.ElementType.Resolve(); retType = new GenericInstanceType(elType); var elTypeImporter = Helpers.CreateTypeImporter(elType, Session, importList, options); elTypeImporter.ImportFinished += t => { var newType = new GenericInstanceType((TypeReference)t); foreach (var a in retType.GenericArguments) { newType.GenericArguments.Add(a); } retType = newType; }; //Throws if cancellation was requested options.CancellationToken.ThrowIfCancellationRequested(); //Imports the arguments foreach (var a in type.GenericArguments) { var arg = a; if (a is GenericParameter) { importList.Add(MemberImporter.Create((_, __) => { retType.GenericArguments.Add(arg); return(null); })); } else { var argImporter = Helpers.CreateTypeImporter(a, Session, importList, options); argImporter.ImportFinished += x => retType.GenericArguments.Add((TypeReference)x); } } //Throws if cancellation was requested options.CancellationToken.ThrowIfCancellationRequested(); }
protected override void ScanCore(MemberImportingOptions options, List <MemberImporter> importList) { //Method var originalMethod = (MethodDefinition)Member; methodClone = originalMethod.Clone(Session); //Imports the generic parameters if (methodClone.HasGenericParameters) { importList.Add(new GenericParametersImporter(methodClone, methodClone, Session).Scan(options)); methodClone.GenericParameters.Clear(); } //Imports the attributes if (methodClone.HasCustomAttributes) { importList.Add(new CustomAttributesImporter(methodClone, methodClone, Session).Scan(options)); methodClone.CustomAttributes.Clear(); } //Imports the return type var retImporter = Helpers.CreateTypeImporter(originalMethod.ReturnType, Session, importList, options); retImporter.ImportFinished += t => methodClone.ReturnType = (TypeReference)t; //Imports the attributes of the return type if (methodClone.MethodReturnType.HasCustomAttributes) { importList.Add(new CustomAttributesImporter(methodClone.MethodReturnType, methodClone.MethodReturnType, Session).Scan(options)); methodClone.MethodReturnType.CustomAttributes.Clear(); } //Imports the parameters foreach (var p in originalMethod.Parameters) { //Creates a new parameter var param = new ParameterDefinition(p.Name, p.Attributes, p.ParameterType) { Constant = p.Constant, MarshalInfo = p.MarshalInfo, MetadataToken = new MetadataToken(p.MetadataToken.TokenType, GlobalContainer.GetFreeRID(Session.DestinationModule)) }; methodClone.Parameters.Add(param); //Queues importing of custom attributes if (p.HasCustomAttributes) { importList.Add(new CustomAttributesImporter(p, param, Session).Scan(options)); param.CustomAttributes.Clear(); } //Queues importing of type var typeImporter = Helpers.CreateTypeImporter(p.ParameterType, Session, importList, options); typeImporter.ImportFinished += t => param.ParameterType = (TypeReference)t; } //Clones the body var originalBody = originalMethod.Body; var body = methodClone.Body; body.InitLocals = originalBody.InitLocals; body.MaxStackSize = originalBody.MaxStackSize; //Clones the variables foreach (var v in originalBody.Variables) { var var = new VariableDefinition(v.Name, v.VariableType); var typeImporter = Helpers.CreateTypeImporter(var.VariableType, Session, importList, options); typeImporter.ImportFinished += t => var.VariableType = (TypeReference)t; body.Variables.Add(var); } //Clones the instructions foreach (var x in originalBody.Instructions) { //Creates a new instruction with the same opcode var i = x; var instruction = Instruction.Create(OpCodes.Nop); instruction.OpCode = i.OpCode; body.Instructions.Add(instruction); instruction.Offset = i.Offset; //Switches on the type of the opcode to switch (i.OpCode.OperandType) { //Delays the importing of the operand case OperandType.ShortInlineBrTarget: case OperandType.InlineBrTarget: var index = originalBody.Instructions.IndexOf((Instruction)i.Operand); importList.Add(MemberImporter.Create((_, __) => { instruction.Operand = body.Instructions[index]; return(null); })); break; case OperandType.InlineSwitch: var indexes = ((Instruction[])i.Operand).Select(a => originalBody.Instructions.IndexOf(a)).ToArray(); importList.Add(MemberImporter.Create((_, __) => { instruction.Operand = indexes.Select(a => body.Instructions[a]).ToArray(); return(null); })); break; //Registers importing of the type case OperandType.InlineType: var importer = Helpers.CreateTypeImporter((TypeReference)i.Operand, Session, importList, options); importer.ImportFinished += t => instruction.Operand = t; break; //Registers importing of the declaring type //along with the field type case OperandType.InlineField: var field = (FieldReference)i.Operand; field = new FieldReference(field.Name, field.FieldType, field.DeclaringType); Helpers.CreateTypeImporter(field.DeclaringType, Session, importList, options) .ImportFinished += t => field.DeclaringType = (TypeReference)t; Helpers.CreateTypeImporter(field.FieldType, Session, importList, options) .ImportFinished += t => field.FieldType = (TypeReference)t; instruction.Operand = field; break; //Registers importing of the method case OperandType.InlineMethod: var m = (MethodReference)i.Operand; var methodImporter = MemberImporter.Create((_, __) => { instruction.Operand = Session.DestinationModule.Import(m); return(null); }); importList.Add(methodImporter); break; //Keeps the same operand default: instruction.Operand = i.Operand; break; } } //Imports the overrides if (methodClone.HasOverrides) { foreach (var x in methodClone.Overrides) { var o = x; importList.Add(MemberImporter.Create((_, __) => { methodClone.Overrides.Add(Session.DestinationModule.Import(o)); return(null); })); } methodClone.Overrides.Clear(); } }