private PropertyGrouping HandleProperties(TypeBuilder typeBuilder, Type interfaceType) { var grouping = new PropertyGrouping(InterfaceAndChildren(interfaceType, x => x.GetTypeInfo().GetProperties())); MethodAttributes attributes = MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.HideBySig | MethodAttributes.SpecialName; foreach (var property in grouping.AllProperties) { var propertyBuilder = typeBuilder.DefineProperty(property.PropertyInfo.Name, PropertyAttributes.None, property.PropertyInfo.PropertyType, null); var getter = typeBuilder.DefineMethod(property.PropertyInfo.GetMethod.Name, attributes, property.PropertyInfo.PropertyType, new Type[0]); var setter = typeBuilder.DefineMethod(property.PropertyInfo.SetMethod.Name, attributes, null, new Type[] { property.PropertyInfo.PropertyType }); var backingField = typeBuilder.DefineField("bk_" + property.PropertyInfo.Name, property.PropertyInfo.PropertyType, FieldAttributes.Private); var getterIlGenerator = getter.GetILGenerator(); getterIlGenerator.Emit(OpCodes.Ldarg_0); getterIlGenerator.Emit(OpCodes.Ldfld, backingField); getterIlGenerator.Emit(OpCodes.Ret); propertyBuilder.SetGetMethod(getter); var setterIlGenerator = setter.GetILGenerator(); setterIlGenerator.Emit(OpCodes.Ldarg_0); setterIlGenerator.Emit(OpCodes.Ldarg_1); setterIlGenerator.Emit(OpCodes.Stfld, backingField); setterIlGenerator.Emit(OpCodes.Ret); propertyBuilder.SetSetMethod(setter); property.BackingField = backingField; } return(grouping); }
private void HandleMethods( TypeBuilder typeBuilder, Type interfaceType, FieldBuilder requesterField, FieldInfo classHeadersField, AllowAnyStatusCodeAttribute classAllowAnyStatusCodeAttribute, SerializationMethodsAttribute classSerializationMethodsAttribute, PropertyGrouping properties) { foreach (var methodInfo in InterfaceAndChildren(interfaceType, x => x.GetTypeInfo().GetMethods())) { // Exclude property getter / setters, etc if (methodInfo.IsSpecialName) { continue; } var parameters = methodInfo.GetParameters(); var parameterGrouping = new ParameterGrouping(parameters, methodInfo.Name); var methodBuilder = typeBuilder.DefineMethod(methodInfo.Name, MethodAttributes.Public | MethodAttributes.Virtual, methodInfo.ReturnType, parameters.Select(x => x.ParameterType).ToArray()); var methodIlGenerator = methodBuilder.GetILGenerator(); if (methodInfo == disposeMethod) { this.AddDisposeMethod(methodIlGenerator, requesterField); } else { var requestAttribute = methodInfo.GetCustomAttribute <RequestAttribute>(); if (requestAttribute == null) { throw new ImplementationCreationException(String.Format("Method {0} does not have a suitable [Get] / [Post] / etc attribute on it", methodInfo.Name)); } var allowAnyStatusCodeAttribute = methodInfo.GetCustomAttribute <AllowAnyStatusCodeAttribute>(); var methodSerializationMethodsAttribute = methodInfo.GetCustomAttribute <SerializationMethodsAttribute>(); var serializationMethods = new ResolvedSerializationMethods(classSerializationMethodsAttribute, methodSerializationMethodsAttribute); this.ValidatePathParams(requestAttribute.Path, parameterGrouping.PathParameters.Select(x => x.Attribute.Name ?? x.Parameter.Name).ToList(), properties.Path.Select(x => x.Attribute.Name).ToList(), methodInfo.Name); this.AddRequestInfoCreation(methodIlGenerator, requesterField, requestAttribute); this.AddCancellationTokenIfNeeded(methodIlGenerator, parameterGrouping.CancellationToken); this.AddClassHeadersIfNeeded(methodIlGenerator, classHeadersField); this.AddPropertyHeaders(methodIlGenerator, properties.Headers); this.AddPathProperties(methodIlGenerator, properties.Path); this.AddMethodHeaders(methodIlGenerator, methodInfo); this.AddAllowAnyStatusCodeIfNecessary(methodIlGenerator, allowAnyStatusCodeAttribute ?? classAllowAnyStatusCodeAttribute); this.AddParameters(methodIlGenerator, parameterGrouping, methodInfo.Name, serializationMethods); this.AddRequestMethodInvocation(methodIlGenerator, methodInfo); // Finally, return methodIlGenerator.Emit(OpCodes.Ret); typeBuilder.DefineMethodOverride(methodBuilder, methodInfo); } } }