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); } } }
private void HandleMethods( TypeBuilder typeBuilder, Type interfaceType, FieldBuilder requesterField, FieldInfo classHeadersField, AllowAnyStatusCodeAttribute classAllowAnyStatusCodeAttribute, SerializationMethodsAttribute classSerializationMethodsAttribute, List <KeyValuePair <HeaderAttribute, FieldBuilder> > propertyHeaders) { foreach (var methodInfo in InterfaceAndChildren(interfaceType, x => x.GetMethods())) { // Exclude property getter / setters, etc if (methodInfo.IsSpecialName) { continue; } 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); var parameters = methodInfo.GetParameters(); var parameterGrouping = new ParameterGrouping(parameters, methodInfo.Name); this.ValidatePathParams(requestAttribute.Path, parameterGrouping.PathParameters.Select(x => x.Attribute.Name ?? x.Parameter.Name), methodInfo.Name); var methodBuilder = typeBuilder.DefineMethod(methodInfo.Name, MethodAttributes.Public | MethodAttributes.Virtual, methodInfo.ReturnType, parameters.Select(x => x.ParameterType).ToArray()); var methodIlGenerator = methodBuilder.GetILGenerator(); this.AddRequestInfoCreation(methodIlGenerator, requesterField, requestAttribute); // If there's a cancellationtoken, add that if (parameterGrouping.CancellationToken.HasValue) { methodIlGenerator.Emit(OpCodes.Dup); methodIlGenerator.Emit(OpCodes.Ldarg, (short)parameterGrouping.CancellationToken.Value.Index); methodIlGenerator.Emit(OpCodes.Callvirt, cancellationTokenSetter); } // If there are any class headers, add them if (classHeadersField != null) { // requestInfo.ClassHeaders = classHeaders methodIlGenerator.Emit(OpCodes.Dup); methodIlGenerator.Emit(OpCodes.Ldsfld, classHeadersField); methodIlGenerator.Emit(OpCodes.Callvirt, setClassHeadersMethod); } // If there are any property headers, add them foreach (var propertyHeader in propertyHeaders) { var typedMethod = addPropertyHeaderMethod.MakeGenericMethod(propertyHeader.Value.FieldType); methodIlGenerator.Emit(OpCodes.Dup); methodIlGenerator.Emit(OpCodes.Ldstr, propertyHeader.Key.Name); methodIlGenerator.Emit(OpCodes.Ldarg_0); methodIlGenerator.Emit(OpCodes.Ldfld, propertyHeader.Value); if (propertyHeader.Key.Value == null) { methodIlGenerator.Emit(OpCodes.Ldnull); } else { methodIlGenerator.Emit(OpCodes.Ldstr, propertyHeader.Key.Value); } methodIlGenerator.Emit(OpCodes.Callvirt, typedMethod); } // If there are any method headers, add them var methodHeaders = methodInfo.GetCustomAttributes <HeaderAttribute>(); foreach (var methodHeader in methodHeaders) { if (methodHeader.Name.Contains(':')) { throw new ImplementationCreationException(String.Format("[Header(\"{0}\")] on method {1} must not have colon in its name", methodHeader.Name, methodInfo.Name)); } this.AddMethodHeader(methodIlGenerator, methodHeader); } // If we want to allow any status code, set that var resolvedAllowAnyStatusAttribute = allowAnyStatusCodeAttribute ?? classAllowAnyStatusCodeAttribute; if (resolvedAllowAnyStatusAttribute != null && resolvedAllowAnyStatusAttribute.AllowAnyStatusCode) { methodIlGenerator.Emit(OpCodes.Dup); methodIlGenerator.Emit(OpCodes.Ldc_I4_1); methodIlGenerator.Emit(OpCodes.Callvirt, allowAnyStatusCodeSetter); } this.AddParameters(methodIlGenerator, parameterGrouping, methodInfo.Name, serializationMethods); this.AddRequestMethodInvocation(methodIlGenerator, methodInfo); // Finally, return methodIlGenerator.Emit(OpCodes.Ret); typeBuilder.DefineMethodOverride(methodBuilder, methodInfo); } }
public ResolvedSerializationMethods(SerializationMethodsAttribute classAttribute, SerializationMethodsAttribute methodAttribute) { this.ClassAttribute = classAttribute; this.MethodAttribute = methodAttribute; }
public ResolvedSerializationMethods(SerializationMethodsAttribute classAttribute, SerializationMethodsAttribute methodAttribute) { this.ClassAttribute = classAttribute; this.MethodAttribute = methodAttribute; }