private void WriteJsonConverterWorker() { WriteAutoGenerationDisclaimer(); WriteBlankLine(); // TODO: Dynamically generate this with input types as a factor. WriteLine("using System;"); WriteLine("using System.Buffers;"); WriteLine("using System.Collections.Generic;"); WriteLine("using System.Runtime.InteropServices;"); WriteLine("using System.Text.Json;"); WriteLine("using System.Text.Json.Serialization;"); WriteBlankLine(); BeginNewControlBlock($"namespace {_outputNamespace}"); WriteConverterDeclaration(); WriteProtectedConstructor(); WriteStaticConverterInstanceField(); if (_type.IsArray) { WriteConverterReadMethodForArray(); WriteConverterWriteMethodForArray(); } else if (_type.IsGenericType) { if (_type.GetGenericTypeDefinition().Equals(typeof(List <>))) { WriteConverterReadMethodForListOfT(); WriteConverterWriteMethodForListOfT(); } if (_type.GetGenericTypeDefinition().Equals(typeof(Dictionary <,>)) && _type.GetGenericArguments()[0].Equals(typeof(string))) { WriteConverterReadMethodForDictionaryOfStringToTValue(); WriteConverterWriteMethodForDictionaryOfStringToTValue(); } } else if (!_metadataLoadContext.Resolve <IEnumerable>().IsAssignableFrom(_type)) { WritePropertyNameConstants(); WriteConverterReadMethodForObject(); WriteConverterWriteMethodForObject(); } WriteControlBlockEnd(); WriteControlBlockEnd(); }
public JsonCodeGenerator(MetadataLoadContext metadataLoadContext, string outputNamespace) { if (string.IsNullOrWhiteSpace(outputNamespace)) { throw new ArgumentException(string.Format("{0} is null, empty, or is whitespace", outputNamespace), "outputNamespace"); } _outputNamespace = outputNamespace; _metadataLoadContext = metadataLoadContext; for (int i = 0; i < simpleTypes.Count; i++) { simpleTypes[i] = _metadataLoadContext.Resolve(simpleTypes[i]); } }
private void Generate(MethodModel method) { // [DebuggerStepThrough] WriteLine($"[{S(typeof(DebuggerStepThroughAttribute))}]"); WriteLine($"public async {S(typeof(Task))} {method.MethodInfo.Name}({S(typeof(HttpContext))} httpContext)"); WriteLine("{"); Indent(); var ctors = _model.HandlerType.GetConstructors(); if (ctors.Length > 1 || ctors[0].GetParameters().Length > 0) { // Lazy, defer to DI system if WriteLine($"var handler = ({S(_model.HandlerType)})_factory(httpContext.RequestServices, {S(typeof(Array))}.Empty<{S(typeof(object))}>());"); } else { WriteLine($"var handler = new {S(_model.HandlerType)}();"); } // Declare locals var hasFromBody = false; var hasFromForm = false; foreach (var parameter in method.Parameters) { var parameterName = "arg_" + parameter.Name.Replace("_", "__"); if (parameter.ParameterType.Equals(typeof(HttpContext))) { WriteLine($"var {parameterName} = httpContext;"); } else if (parameter.ParameterType.Equals(typeof(IFormCollection))) { WriteLine($"var {parameterName} = await httpContext.Request.ReadFormAsync();"); } else if (parameter.FromRoute != null) { GenerateConvert(parameterName, parameter.ParameterType, parameter.FromRoute, "httpContext.Request.RouteValues", nullable: true); } else if (parameter.FromQuery != null) { GenerateConvert(parameterName, parameter.ParameterType, parameter.FromQuery, "httpContext.Request.Query"); } else if (parameter.FromHeader != null) { GenerateConvert(parameterName, parameter.ParameterType, parameter.FromHeader, "httpContext.Request.Headers"); } else if (parameter.FromServices) { WriteLine($"var {parameterName} = httpContext.RequestServices.GetRequiredService<{S(parameter.ParameterType)}>();"); } else if (parameter.FromForm != null) { if (!hasFromForm) { WriteLine($"var formCollection = await httpContext.Request.ReadFormAsync();"); hasFromForm = true; } GenerateConvert(parameterName, parameter.ParameterType, parameter.FromForm, "formCollection"); } else if (parameter.FromBody) { if (!hasFromBody) { WriteLine($"var reader = httpContext.RequestServices.GetService<{S(typeof(IHttpRequestReader))}>() ?? _requestReader;"); hasFromBody = true; } if (!parameter.ParameterType.Equals(typeof(JsonElement))) { FromBodyTypes.Add(parameter.ParameterType); } WriteLine($"var {parameterName} = ({S(parameter.ParameterType)})await reader.ReadAsync(httpContext, typeof({S(parameter.ParameterType)}));"); } } AwaitableInfo awaitableInfo = default; // Populate locals if (method.MethodInfo.ReturnType.Equals(typeof(void))) { Write(""); } else { if (AwaitableInfo.IsTypeAwaitable(method.MethodInfo.ReturnType, out awaitableInfo)) { if (awaitableInfo.ResultType.Equals(typeof(void))) { Write("await "); } else { Write("var result = await "); } } else { Write("var result = "); } } WriteNoIndent($"handler.{method.MethodInfo.Name}("); bool first = true; foreach (var parameter in method.Parameters) { var parameterName = "arg_" + parameter.Name.Replace("_", "__"); if (!first) { WriteNoIndent(", "); } WriteNoIndent(parameterName); first = false; } WriteLineNoIndent(");"); var unwrappedType = awaitableInfo.ResultType ?? method.MethodInfo.ReturnType; if (_metadataLoadContext.Resolve <Result>().IsAssignableFrom(unwrappedType)) { WriteLine("await result.ExecuteAsync(httpContext);"); } else if (!unwrappedType.Equals(typeof(void))) { WriteLine($"await new {S(typeof(ObjectResult))}(result).ExecuteAsync(httpContext);"); } Unindent(); WriteLine("}"); WriteLine(""); }
private void Generate(MethodModel method) { // [DebuggerStepThrough] WriteLine($"[{typeof(DebuggerStepThroughAttribute)}]"); var methodStartIndex = _codeBuilder.Length + 4 * _indent; WriteLine($"public async {typeof(Task)} {method.UniqueName}({typeof(HttpContext)} httpContext)"); WriteLine("{"); Indent(); var ctors = _model.HandlerType.GetConstructors(); if (!method.MethodInfo.IsStatic) { if (ctors.Length > 1 || ctors[0].GetParameters().Length > 0) { // Lazy, defer to DI system if WriteLine($"var handler = ({S(_model.HandlerType)})_factory(httpContext.RequestServices, {typeof(Array)}.Empty<{typeof(object)}>());"); } else { WriteLine($"var handler = new {S(_model.HandlerType)}();"); } } // Declare locals var hasAwait = false; var hasFromBody = false; var hasFromForm = false; foreach (var parameter in method.Parameters) { var parameterName = "arg_" + parameter.Name.Replace("_", "__"); if (parameter.ParameterType.Equals(typeof(HttpContext))) { WriteLine($"var {parameterName} = httpContext;"); } else if (parameter.ParameterType.Equals(typeof(IFormCollection))) { WriteLine($"var {parameterName} = await httpContext.Request.ReadFormAsync();"); hasAwait = true; } else if (parameter.FromRoute != null) { GenerateConvert(parameterName, parameter.ParameterType, parameter.FromRoute, "httpContext.Request.RouteValues", nullable: true); } else if (parameter.FromQuery != null) { GenerateConvert(parameterName, parameter.ParameterType, parameter.FromQuery, "httpContext.Request.Query"); } else if (parameter.FromHeader != null) { GenerateConvert(parameterName, parameter.ParameterType, parameter.FromHeader, "httpContext.Request.Headers"); } else if (parameter.FromServices) { WriteLine($"var {parameterName} = httpContext.RequestServices.GetRequiredService<{S(parameter.ParameterType)}>();"); } else if (parameter.FromForm != null) { if (!hasFromForm) { WriteLine($"var formCollection = await httpContext.Request.ReadFormAsync();"); hasAwait = true; hasFromForm = true; } GenerateConvert(parameterName, parameter.ParameterType, parameter.FromForm, "formCollection"); } else if (parameter.FromBody) { if (!hasFromBody) { hasFromBody = true; } if (!parameter.ParameterType.Equals(typeof(JsonElement))) { FromBodyTypes.Add(parameter.ParameterType); } WriteLine($"var {parameterName} = await httpContext.Request.ReadFromJsonAsync<{S(parameter.ParameterType)}>();"); hasAwait = true; } else { WriteLine($"{S(parameter.ParameterType)} {parameterName} = default;"); } } AwaitableInfo awaitableInfo = default; // Populate locals if (method.MethodInfo.ReturnType.Equals(typeof(void))) { Write(""); } else { if (AwaitableInfo.IsTypeAwaitable(method.MethodInfo.ReturnType, out awaitableInfo)) { if (awaitableInfo.ResultType.Equals(typeof(void))) { if (hasAwait) { Write("await "); } else { Write("return "); } } else { Write("var result = await "); hasAwait = true; } } else { Write("var result = "); } } WriteNoIndent($"{(method.MethodInfo.IsStatic ? S(_model.HandlerType) : "handler")}.{method.MethodInfo.Name}("); bool first = true; foreach (var parameter in method.Parameters) { var parameterName = "arg_" + parameter.Name.Replace("_", "__"); if (!first) { WriteNoIndent(", "); } WriteNoIndent(parameterName); first = false; } WriteLineNoIndent(");"); if (!hasAwait) { // Remove " async" from method signature. _codeBuilder.Remove(methodStartIndex + 6, 6); } void AwaitOrReturn(string executeAsync) { if (hasAwait) { Write("await "); } else { Write("return "); } WriteLineNoIndent(executeAsync); } var unwrappedType = awaitableInfo.ResultType ?? method.MethodInfo.ReturnType; if (_metadataLoadContext.Resolve <IResult>().IsAssignableFrom(unwrappedType)) { AwaitOrReturn("result.ExecuteAsync(httpContext);"); } else if (unwrappedType.Equals(typeof(string))) { AwaitOrReturn($"httpContext.Response.WriteAsync(result);"); } else if (!unwrappedType.Equals(typeof(void))) { AwaitOrReturn($"httpContext.Response.WriteAsJsonAsync(result);"); } else if (!hasAwait && method.MethodInfo.ReturnType.Equals(typeof(void))) { // If awaitableInfo.ResultType is void, we've already returned the awaitable directly. WriteLine($"return {typeof(Task)}.CompletedTask;"); } Unindent(); WriteLine("}"); WriteLine(""); }