protected override void ScanCore(MemberImportingOptions options, List <MemberImporter> importList) { //Property var originalProp = (PropertyDefinition)Member; propClone = originalProp.Clone(Session); //Registers importing of custom attributes if (propClone.HasCustomAttributes) { importList.Add(new CustomAttributesImporter(propClone, propClone, Session).Scan(options)); propClone.CustomAttributes.Clear(); } //Registers importing of get and set methods if (propClone.GetMethod != null) { var importer = new MethodImporter(propClone.GetMethod, Destination, Session, false).Scan(options); importer.ImportFinished += m => { var get = (MethodDefinition)m; get.IsGetter = true; propClone.GetMethod = get; }; importList.Add(importer); } if (propClone.SetMethod != null) { var importer = new MethodImporter(propClone.SetMethod, Destination, Session, false).Scan(options); importer.ImportFinished += m => { var set = (MethodDefinition)m; set.IsSetter = true; propClone.SetMethod = set; }; importList.Add(importer); } //Imports other methods if (originalProp.HasOtherMethods) { foreach (var m in originalProp.OtherMethods) { var importer = new MethodImporter(m, Destination, Session, false).Scan(options); importer.ImportFinished += x => { var method = (MethodDefinition)x; method.IsOther = true; propClone.OtherMethods.Add(method); }; importList.Add(importer); } } //Imports the parameters foreach (var p in originalProp.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)) }; propClone.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; } }
public void Inject(ICSharpCode.ILSpy.TreeNodes.ILSpyTreeNode node, string name, Mono.Cecil.IMetadataTokenProvider member) { //Type var type = (TypeDefinition)((IMemberTreeNode)node).Member; //Event type var eventType = type.Module.Import((TypeReference)member, type); //Creates the event var evt = new EventDefinition(name, EventAttributes.None, eventType) { MetadataToken = new MetadataToken(TokenType.Event, GlobalContainer.GetFreeRID(type.Module)) }; //Creates the field FieldReference backingField = null; if (!type.IsInterface) { backingField = new FieldDefinition( name, FieldAttributes.Private, eventType ) { MetadataToken = new MetadataToken(TokenType.Field, GlobalContainer.GetFreeRID(type.Module)) }; type.Fields.Add((FieldDefinition)backingField); } //Checks if the type is generic if (type.HasGenericParameters) { var giType = new GenericInstanceType(type); foreach (var x in type.GenericParameters) { giType.GenericArguments.Add(x); } backingField = new FieldReference(backingField.Name, eventType, giType); } //Creates the addon method evt.AddMethod = new MethodDefinition( "add_" + name, MethodAttributes.Public | MethodAttributes.SpecialName, type.Module.TypeSystem.Void ) { IsSynchronized = !type.IsInterface, IsAddOn = true, MetadataToken = new MetadataToken(TokenType.Method, GlobalContainer.GetFreeRID(type.Module)), Parameters = { new ParameterDefinition("value", ParameterAttributes.None, eventType) } }; //Checks if the destination type is an interface if (type.IsInterface) { evt.AddMethod.Attributes |= MethodAttributes.NewSlot | MethodAttributes.CheckAccessOnOverride | MethodAttributes.Abstract | MethodAttributes.Virtual; } else { //Writes the instruction of the addon method var addBody = evt.AddMethod.Body; addBody.MaxStackSize = 8; addBody.GetType().GetField("code_size", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance).SetValue(addBody, 1); var addIL = addBody.GetILProcessor(); addIL.Emit(OpCodes.Ldarg_0); addIL.Emit(OpCodes.Ldarg_0); addIL.Emit(OpCodes.Ldfld, backingField); addIL.Emit(OpCodes.Ldarg_1); //Delegate.Combine(Delegate, Delegate) addIL.Emit(OpCodes.Call, type.Module.Import(new TypeReference("System", "Delegate", type.Module, type.Module.TypeSystem.Corlib).Resolve().Methods.First(x => x.Name == "Combine" && x.IsStatic && x.Parameters.Count == 2 && x.Parameters.All(p => p.ParameterType.FullName == "System.Delegate")))); addIL.Emit(OpCodes.Castclass, eventType); addIL.Emit(OpCodes.Stfld, backingField); addIL.Emit(OpCodes.Ret); } //Creates the removeon method evt.RemoveMethod = new MethodDefinition( "remove_" + name, MethodAttributes.Public | MethodAttributes.SpecialName, type.Module.TypeSystem.Void ) { IsSynchronized = !type.IsInterface, IsRemoveOn = true, MetadataToken = new MetadataToken(TokenType.Method, GlobalContainer.GetFreeRID(type.Module)), Parameters = { new ParameterDefinition("value", ParameterAttributes.None, eventType) } }; //Checks if the destination type is an interface if (type.IsInterface) { evt.RemoveMethod.Attributes |= MethodAttributes.NewSlot | MethodAttributes.CheckAccessOnOverride | MethodAttributes.Abstract | MethodAttributes.Virtual; } else { //Writes the instruction of the removeon method var removeBody = evt.RemoveMethod.Body; removeBody.MaxStackSize = 8; removeBody.GetType().GetField("code_size", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance).SetValue(removeBody, 1); var removeIL = removeBody.GetILProcessor(); removeIL.Emit(OpCodes.Ldarg_0); removeIL.Emit(OpCodes.Ldarg_0); removeIL.Emit(OpCodes.Ldfld, backingField); removeIL.Emit(OpCodes.Ldarg_1); //Delegate.Remove(Delegate, Delegate) removeIL.Emit(OpCodes.Call, type.Module.Import(new TypeReference("System", "Delegate", type.Module, type.Module.TypeSystem.Corlib).Resolve().Methods.First(x => x.Name == "Remove" && x.IsStatic && x.Parameters.Count == 2 && x.Parameters.All(p => p.ParameterType.FullName == "System.Delegate")))); removeIL.Emit(OpCodes.Castclass, eventType); removeIL.Emit(OpCodes.Stfld, backingField); removeIL.Emit(OpCodes.Ret); } //Adds the members to the type type.Methods.Add(evt.AddMethod); type.Methods.Add(evt.RemoveMethod); type.Events.Add(evt); evt.AddMethod.Overrides.Clear(); evt.RemoveMethod.Overrides.Clear(); //Creates the nodes if (node is TypeTreeNode) { if (!type.IsInterface) { node.Children.Add(new ILEditTreeNode(backingField, true)); } node.Children.Add(new ILEditTreeNode(evt, false)); Helpers.Tree.SortChildren((TypeTreeNode)node); } else if (node is ILEditTreeNode) { ((ILEditTreeNode)node).RefreshChildren(); } }
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(); } }