private MethodDefinition ExposeMethod(TypeDefinition typeToProcess, FieldReference fieldToProcess, MethodReference methodToExpose, ExposeMode exposeMode, MethodSemanticsAttributes semanticAttributes) { var typeToExpose = fieldToProcess.FieldType; var genericTypeToExpose = typeToExpose as GenericInstanceType; MethodReference methodToExposeWithResolvedGenerics = null; if (genericTypeToExpose != null) { methodToExposeWithResolvedGenerics = methodToExpose.With(declaringType: methodToExpose.DeclaringType.MakeGenericInstanceType(genericTypeToExpose.GenericArguments.ToArray()), resolveGenericReturnTypeAndParameterTypes: true); methodToExpose = methodToExpose.With(declaringType: methodToExpose.DeclaringType.MakeGenericInstanceType(genericTypeToExpose.GenericArguments.ToArray()), resolveGenericReturnTypeAndParameterTypes: false); } var name = exposeMode == ExposeMode.ImplementExplicit ? typeToExpose.FullName + "." + methodToExpose.Name : methodToExpose.Name; MethodAttributes methodAttributes = (exposeMode == ExposeMode.ImplementExplicit ? MethodAttributes.Private : MethodAttributes.Public); if (exposeMode == ExposeMode.ImplementImplicit || exposeMode == ExposeMode.ImplementExplicit) { methodAttributes |= MethodAttributes.Final; } methodAttributes |= MethodAttributes.HideBySig; if (semanticAttributes != MethodSemanticsAttributes.None) { methodAttributes |= MethodAttributes.SpecialName; } if (exposeMode == ExposeMode.ImplementImplicit || exposeMode == ExposeMode.ImplementExplicit) { methodAttributes |= MethodAttributes.NewSlot | MethodAttributes.Virtual; } var method = new MethodDefinition(name, methodAttributes, (methodToExposeWithResolvedGenerics ?? methodToExpose).ReturnType); foreach (var genericParameter in (methodToExposeWithResolvedGenerics ?? methodToExpose).GenericParameters) { method.GenericParameters.Add(new GenericParameter(genericParameter.Name, method)); } foreach (var parameter in (methodToExposeWithResolvedGenerics ?? methodToExpose).Parameters) { method.Parameters.Add(new ParameterDefinition(parameter.Name, parameter.Attributes, parameter.ParameterType)); } var existingMethod = typeToProcess.GetMethodLike(method); if (existingMethod != null) { return(existingMethod); } bool methodReturnsVoid = method.ReturnType.FullName == ModuleDefinition.TypeSystem.Void.FullName; if (!methodReturnsVoid) { method.Body.Variables.Add(new VariableDefinition(method.ReturnType)); method.Body.InitLocals = true; } var instructions = method.Body.Instructions; instructions.Add(Instruction.Create(OpCodes.Nop)); instructions.Add(Instruction.Create(OpCodes.Ldarg_0)); // Load this instructions.Add(Instruction.Create(OpCodes.Ldfld, fieldToProcess.DeclaringType.HasGenericParameters ? fieldToProcess.With(declaringType: fieldToProcess.DeclaringType.MakeGenericInstanceTypeWithGenericParametersAsGenericArguments()) : fieldToProcess) ); if (methodToExpose.Parameters.Count >= 1) { instructions.Add(Instruction.Create(OpCodes.Ldarg_1)); } if (methodToExpose.Parameters.Count >= 2) { instructions.Add(Instruction.Create(OpCodes.Ldarg_2)); } if (methodToExpose.Parameters.Count >= 3) { instructions.Add(Instruction.Create(OpCodes.Ldarg_3)); } if (methodToExpose.Parameters.Count >= 4) { for (var i = 3; i < methodToExpose.Parameters.Count; i++) { instructions.Add(Instruction.Create(OpCodes.Ldarg_S, i + 1)); } } instructions.Add(Instruction.Create(OpCodes.Callvirt, methodToExpose.HasGenericParameters ? methodToExpose.MakeGenericInstanceMethod(method.GenericParameters.ToArray()) : methodToExpose)); if (methodReturnsVoid) { instructions.Add(Instruction.Create(OpCodes.Nop)); } else { instructions.Add(Instruction.Create(OpCodes.Stloc_0)); var inst = Instruction.Create(OpCodes.Ldloc_0); instructions.Add(Instruction.Create(OpCodes.Br_S, inst)); instructions.Add(inst); } instructions.Add(Instruction.Create(OpCodes.Ret)); if (exposeMode == ExposeMode.ImplementExplicit) { method.Overrides.Add(methodToExpose); } AddFodyGeneratedAttributes(method); typeToProcess.Methods.Add(method); return(method); }
private PropertyDefinition ExposeProperty(TypeDefinition typeToProcess, FieldReference fieldToProcess, PropertyDefinition propertyToExpose, ExposeMode exposeMode) { var typeToExpose = fieldToProcess.FieldType; var genericTypeToExpose = typeToExpose as GenericInstanceType; var name = exposeMode == ExposeMode.ImplementExplicit ? typeToExpose.FullName + "." + propertyToExpose.Name : propertyToExpose.Name; var propertyToExposeType = genericTypeToExpose == null ? propertyToExpose.PropertyType : propertyToExpose.ResolveGenericPropertyType(genericTypeToExpose.GenericArguments); var property = new PropertyDefinition(name, PropertyAttributes.None, propertyToExposeType); if (propertyToExpose.GetMethod != null && propertyToExpose.GetMethod.IsPublic) { var getMethod = ExposeMethod(typeToProcess, fieldToProcess, propertyToExpose.GetMethod, exposeMode, MethodSemanticsAttributes.Getter); getMethod.SemanticsAttributes = MethodSemanticsAttributes.Getter; property.GetMethod = getMethod; } var existingProperty = typeToProcess.GetPropertyLike(property); if (existingProperty != null) { return(existingProperty); } if (propertyToExpose.SetMethod != null && propertyToExpose.SetMethod.IsPublic) { var setMethod = ExposeMethod(typeToProcess, fieldToProcess, propertyToExpose.SetMethod, exposeMode, MethodSemanticsAttributes.Setter); setMethod.SemanticsAttributes = MethodSemanticsAttributes.Setter; property.SetMethod = setMethod; } AddFodyGeneratedAttributes(property); typeToProcess.Properties.Add(property); return(property); }
private EventDefinition ExposeEvent(TypeDefinition typeToProcess, FieldReference fieldToProcess, EventDefinition eventToExpose, ExposeMode exposeMode) { var typeToExpose = fieldToProcess.FieldType; var genericTypeToExpose = typeToExpose as GenericInstanceType; var eventToExposeType = genericTypeToExpose == null ? eventToExpose.EventType : eventToExpose.ResolveGenericEventType(genericTypeToExpose.GenericArguments); var name = exposeMode == ExposeMode.ImplementExplicit ? typeToExpose.FullName + "." + eventToExpose.Name : eventToExpose.Name; var @event = new EventDefinition(name, EventAttributes.None, eventToExposeType); var existingEvent = typeToProcess.GetEventLike(@event); if (existingEvent != null) { return(existingEvent); } if (eventToExpose.AddMethod != null && eventToExpose.AddMethod.IsPublic) { var addMethod = ExposeMethod(typeToProcess, fieldToProcess, eventToExpose.AddMethod, exposeMode, MethodSemanticsAttributes.AddOn); addMethod.SemanticsAttributes = MethodSemanticsAttributes.AddOn; @event.AddMethod = addMethod; } if (eventToExpose.RemoveMethod != null && eventToExpose.RemoveMethod.IsPublic) { var removeMethod = ExposeMethod(typeToProcess, fieldToProcess, eventToExpose.RemoveMethod, exposeMode, MethodSemanticsAttributes.RemoveOn); removeMethod.SemanticsAttributes = MethodSemanticsAttributes.RemoveOn; @event.RemoveMethod = removeMethod; } AddFodyGeneratedAttributes(@event); typeToProcess.Events.Add(@event); return(@event); }
private void ExposeMembersInternal(TypeDefinition typeToProcess, FieldReference fieldToProcess, ExposeMode exposeMode) { var typeToExpose = fieldToProcess.FieldType; var resolvedTypeToExpose = typeToExpose.Resolve(); foreach (var propertyToExpose in resolvedTypeToExpose.Properties.Public()) { ExposeProperty(typeToProcess, fieldToProcess, propertyToExpose, exposeMode); } foreach (var eventToExpose in resolvedTypeToExpose.Events.Public()) { ExposeEvent(typeToProcess, fieldToProcess, eventToExpose, exposeMode); } foreach (var methodToExpose in resolvedTypeToExpose.Methods.Public().NonSpecial()) { ExposeMethod(typeToProcess, fieldToProcess, methodToExpose, exposeMode, MethodSemanticsAttributes.None); } }
private void ExposeMembersInternal(TypeDefinition typeToProcess, FieldReference fieldToProcess, ExposeMode exposeMode) { var typeToExpose = fieldToProcess.FieldType; var resolvedTypeToExpose = typeToExpose.Resolve(); foreach (var propertyToExpose in resolvedTypeToExpose.Properties.Public()) ExposeProperty(typeToProcess, fieldToProcess, propertyToExpose, exposeMode); foreach (var eventToExpose in resolvedTypeToExpose.Events.Public()) ExposeEvent(typeToProcess, fieldToProcess, eventToExpose, exposeMode); foreach (var methodToExpose in resolvedTypeToExpose.Methods.Public().NonSpecial()) ExposeMethod(typeToProcess, fieldToProcess, methodToExpose, exposeMode, MethodSemanticsAttributes.None); }
private MethodDefinition ExposeMethod(TypeDefinition typeToProcess, FieldReference fieldToProcess, MethodReference methodToExpose, ExposeMode exposeMode, MethodSemanticsAttributes semanticAttributes) { var typeToExpose = fieldToProcess.FieldType; var genericTypeToExpose = typeToExpose as GenericInstanceType; MethodReference methodToExposeWithResolvedGenerics = null; if (genericTypeToExpose != null) { methodToExposeWithResolvedGenerics = methodToExpose.With(declaringType: methodToExpose.DeclaringType.MakeGenericInstanceType(genericTypeToExpose.GenericArguments.ToArray()), resolveGenericReturnTypeAndParameterTypes: true); methodToExpose = methodToExpose.With(declaringType: methodToExpose.DeclaringType.MakeGenericInstanceType(genericTypeToExpose.GenericArguments.ToArray()), resolveGenericReturnTypeAndParameterTypes: false); } var name = exposeMode == ExposeMode.ImplementExplicit ? typeToExpose.FullName + "." + methodToExpose.Name : methodToExpose.Name; MethodAttributes methodAttributes = (exposeMode == ExposeMode.ImplementExplicit ? MethodAttributes.Private : MethodAttributes.Public); if (exposeMode == ExposeMode.ImplementImplicit || exposeMode == ExposeMode.ImplementExplicit) methodAttributes |= MethodAttributes.Final; methodAttributes |= MethodAttributes.HideBySig; if (semanticAttributes != MethodSemanticsAttributes.None) methodAttributes |= MethodAttributes.SpecialName; if (exposeMode == ExposeMode.ImplementImplicit || exposeMode == ExposeMode.ImplementExplicit) methodAttributes |= MethodAttributes.NewSlot | MethodAttributes.Virtual; var method = new MethodDefinition(name, methodAttributes, (methodToExposeWithResolvedGenerics ?? methodToExpose).ReturnType); foreach (var genericParameter in (methodToExposeWithResolvedGenerics ?? methodToExpose).GenericParameters) { method.GenericParameters.Add(new GenericParameter(genericParameter.Name, method)); } foreach (var parameter in (methodToExposeWithResolvedGenerics ?? methodToExpose).Parameters) { method.Parameters.Add(new ParameterDefinition(parameter.Name, parameter.Attributes, parameter.ParameterType)); } var existingMethod = typeToProcess.GetMethodLike(method); if (existingMethod != null) return existingMethod; bool methodReturnsVoid = method.ReturnType.FullName == ModuleDefinition.TypeSystem.Void.FullName; if (!methodReturnsVoid) { method.Body.Variables.Add(new VariableDefinition(method.ReturnType)); method.Body.InitLocals = true; } var instructions = method.Body.Instructions; instructions.Add(Instruction.Create(OpCodes.Nop)); instructions.Add(Instruction.Create(OpCodes.Ldarg_0)); // Load this instructions.Add(Instruction.Create(OpCodes.Ldfld, fieldToProcess.DeclaringType.HasGenericParameters ? fieldToProcess.With(declaringType: fieldToProcess.DeclaringType.MakeGenericInstanceTypeWithGenericParametersAsGenericArguments()) : fieldToProcess) ); if (methodToExpose.Parameters.Count >= 1) instructions.Add(Instruction.Create(OpCodes.Ldarg_1)); if (methodToExpose.Parameters.Count >= 2) instructions.Add(Instruction.Create(OpCodes.Ldarg_2)); if (methodToExpose.Parameters.Count >= 3) instructions.Add(Instruction.Create(OpCodes.Ldarg_3)); if (methodToExpose.Parameters.Count >= 4) { for (var i = 3; i < methodToExpose.Parameters.Count; i++) { instructions.Add(Instruction.Create(OpCodes.Ldarg_S, i + 1)); } } instructions.Add(Instruction.Create(OpCodes.Callvirt, methodToExpose.HasGenericParameters ? methodToExpose.MakeGenericInstanceMethod(method.GenericParameters.ToArray()) : methodToExpose)); if (methodReturnsVoid) instructions.Add(Instruction.Create(OpCodes.Nop)); else { instructions.Add(Instruction.Create(OpCodes.Stloc_0)); var inst = Instruction.Create(OpCodes.Ldloc_0); instructions.Add(Instruction.Create(OpCodes.Br_S, inst)); instructions.Add(inst); } instructions.Add(Instruction.Create(OpCodes.Ret)); if (exposeMode == ExposeMode.ImplementExplicit) method.Overrides.Add(methodToExpose); AddFodyGeneratedAttributes(method); typeToProcess.Methods.Add(method); return method; }
private EventDefinition ExposeEvent(TypeDefinition typeToProcess, FieldReference fieldToProcess, EventDefinition eventToExpose, ExposeMode exposeMode) { var typeToExpose = fieldToProcess.FieldType; var genericTypeToExpose = typeToExpose as GenericInstanceType; var eventToExposeType = genericTypeToExpose == null ? eventToExpose.EventType : eventToExpose.ResolveGenericEventType(genericTypeToExpose.GenericArguments); var name = exposeMode == ExposeMode.ImplementExplicit ? typeToExpose.FullName + "." + eventToExpose.Name : eventToExpose.Name; var @event = new EventDefinition(name, EventAttributes.None, eventToExposeType); var existingEvent = typeToProcess.GetEventLike(@event); if (existingEvent != null) return existingEvent; if (eventToExpose.AddMethod != null && eventToExpose.AddMethod.IsPublic) { var addMethod = ExposeMethod(typeToProcess, fieldToProcess, eventToExpose.AddMethod, exposeMode, MethodSemanticsAttributes.AddOn); addMethod.SemanticsAttributes = MethodSemanticsAttributes.AddOn; @event.AddMethod = addMethod; } if (eventToExpose.RemoveMethod != null && eventToExpose.RemoveMethod.IsPublic) { var removeMethod = ExposeMethod(typeToProcess, fieldToProcess, eventToExpose.RemoveMethod, exposeMode, MethodSemanticsAttributes.RemoveOn); removeMethod.SemanticsAttributes = MethodSemanticsAttributes.RemoveOn; @event.RemoveMethod = removeMethod; } AddFodyGeneratedAttributes(@event); typeToProcess.Events.Add(@event); return @event; }
private PropertyDefinition ExposeProperty(TypeDefinition typeToProcess, FieldReference fieldToProcess, PropertyDefinition propertyToExpose, ExposeMode exposeMode) { var typeToExpose = fieldToProcess.FieldType; var genericTypeToExpose = typeToExpose as GenericInstanceType; var name = exposeMode == ExposeMode.ImplementExplicit ? typeToExpose.FullName + "." + propertyToExpose.Name : propertyToExpose.Name; var propertyToExposeType = genericTypeToExpose == null ? propertyToExpose.PropertyType : propertyToExpose.ResolveGenericPropertyType(genericTypeToExpose.GenericArguments); var property = new PropertyDefinition(name, PropertyAttributes.None, propertyToExposeType); if (propertyToExpose.GetMethod != null && propertyToExpose.GetMethod.IsPublic) { var getMethod = ExposeMethod(typeToProcess, fieldToProcess, propertyToExpose.GetMethod, exposeMode, MethodSemanticsAttributes.Getter); getMethod.SemanticsAttributes = MethodSemanticsAttributes.Getter; property.GetMethod = getMethod; } var existingProperty = typeToProcess.GetPropertyLike(property); if (existingProperty != null) return existingProperty; if (propertyToExpose.SetMethod != null && propertyToExpose.SetMethod.IsPublic) { var setMethod = ExposeMethod(typeToProcess, fieldToProcess, propertyToExpose.SetMethod, exposeMode, MethodSemanticsAttributes.Setter); setMethod.SemanticsAttributes = MethodSemanticsAttributes.Setter; property.SetMethod = setMethod; } AddFodyGeneratedAttributes(property); typeToProcess.Properties.Add(property); return property; }