public void Generate(CodeWriterBase writer, Cfg cfg) { if (writer.GetType() != typeof(WriterForCS)) { throw new Exception("For the selected template is currenty only language 'CS' supported!"); } var nsImports = new List <string>(); nsImports.Add("Newtonsoft.Json"); nsImports.Add("System"); nsImports.Add("System.Net"); var inputFileFullPath = Path.GetFullPath(cfg.inputFile); Program.AddResolvePath(Path.GetDirectoryName(inputFileFullPath)); Assembly ass = Assembly.LoadFile(inputFileFullPath); Type[] svcInterfaces; try { svcInterfaces = ass.GetTypes(); } catch (ReflectionTypeLoadException ex) { svcInterfaces = ex.Types.Where((t) => t != null).ToArray(); } //transform patterns to regex cfg.interfaceTypeNamePattern = "^(" + Regex.Escape(cfg.interfaceTypeNamePattern).Replace("\\*", ".*?") + ")$"; svcInterfaces = svcInterfaces.Where((Type i) => Regex.IsMatch(i.FullName, cfg.interfaceTypeNamePattern)).ToArray(); if (!String.IsNullOrWhiteSpace(cfg.outputNamespace) && cfg.customImports.Contains(cfg.outputNamespace)) { nsImports.Remove(cfg.outputNamespace); } foreach (string import in cfg.customImports.Union(nsImports).Distinct().OrderBy((s) => s)) { writer.WriteImport(import); } if (!String.IsNullOrWhiteSpace(cfg.outputNamespace)) { writer.WriteLine(); writer.WriteBeginNamespace(cfg.outputNamespace); } writer.WriteLine(); writer.WriteLineAndPush($"public partial class {cfg.connectorClassName} {{"); writer.WriteLine(); writer.WriteLineAndPush($"public {cfg.connectorClassName}(string url, string apiToken) {{"); writer.WriteLine(); writer.WriteLineAndPush("if (!url.EndsWith(\"/\")) {"); writer.WriteLine("url = url + \"/\";"); writer.PopAndWriteLine("}"); writer.WriteLine(); foreach (Type svcInt in svcInterfaces) { string endpointName = svcInt.Name; if (endpointName[0] == 'I' && Char.IsUpper(endpointName[1])) { endpointName = endpointName.Substring(1); } writer.WriteLine($"_{endpointName}Client = new {endpointName}Client(url + \"{writer.Ftl(endpointName)}/\", apiToken);"); } writer.WriteLine(); writer.PopAndWriteLine("}"); foreach (Type svcInt in svcInterfaces) { string endpointName = svcInt.Name; if (endpointName[0] == 'I' && Char.IsUpper(endpointName[1])) { endpointName = endpointName.Substring(1); } string svcIntDoc = XmlCommentAccessExtensions.GetDocumentation(svcInt); writer.WriteLine(); writer.WriteLine($"private {endpointName}Client _{endpointName}Client = null;"); if (!String.IsNullOrWhiteSpace(svcIntDoc)) { writer.WriteLine($"/// <summary> {svcIntDoc} </summary>"); } writer.WriteLineAndPush($"public {svcInt.Name} {endpointName} {{"); writer.WriteLineAndPush("get {"); writer.WriteLine($"return _{endpointName}Client;"); writer.PopAndWriteLine("}"); writer.PopAndWriteLine("}"); } writer.WriteLine(); writer.PopAndWriteLine("}"); //class foreach (Type svcInt in svcInterfaces) { string endpointName = svcInt.Name; if (endpointName[0] == 'I' && Char.IsUpper(endpointName[1])) { endpointName = endpointName.Substring(1); } string svcIntDoc = XmlCommentAccessExtensions.GetDocumentation(svcInt); writer.WriteLine(); if (!String.IsNullOrWhiteSpace(svcIntDoc)) { writer.WriteLine($"/// <summary> {svcIntDoc} </summary>"); } writer.WriteLineAndPush($"internal partial class {endpointName}Client : {svcInt.Name} {{"); writer.WriteLine(); writer.WriteLine("private string _Url;"); writer.WriteLine("private string _ApiToken;"); writer.WriteLine(); writer.WriteLineAndPush($"public {endpointName}Client(string url, string apiToken) {{"); writer.WriteLine("_Url = url;"); writer.WriteLine("_ApiToken = apiToken;"); writer.PopAndWriteLine("}"); //constructor writer.WriteLine(); writer.WriteLineAndPush($"private WebClient CreateWebClient() {{"); writer.WriteLine("var wc = new WebClient();"); //TODO: make customizable writer.WriteLine("wc.Headers.Set(\"" + cfg.authHeaderName + "\", _ApiToken);"); writer.WriteLine("wc.Headers.Set(\"Content-Type\", \"application/json\");"); writer.WriteLine("return wc;"); writer.PopAndWriteLine("}"); //constructor foreach (MethodInfo svcMth in svcInt.GetMethods()) { string svcMthDoc = XmlCommentAccessExtensions.GetDocumentation(svcMth, true); writer.WriteLine(); if (String.IsNullOrWhiteSpace(svcMthDoc)) { svcMthDoc = svcMth.Name; } writer.WriteLine($"/// <summary> {svcMthDoc} </summary>"); var paramSignature = new List <string>(); foreach (ParameterInfo svcMthPrm in svcMth.GetParameters()) { string svcMthPrmDoc = XmlCommentAccessExtensions.GetDocumentation(svcMthPrm); if (String.IsNullOrWhiteSpace(svcMthPrmDoc)) { svcMthPrmDoc = XmlCommentAccessExtensions.GetDocumentation(svcMthPrm.ParameterType); } if (!String.IsNullOrWhiteSpace(svcMthPrmDoc)) { writer.WriteLine($"/// <param name=\"{svcMthPrm.Name}\"> {svcMthPrmDoc} </param>"); } Type pt = svcMthPrm.ParameterType; string pfx = ""; if (svcMthPrm.IsOut) { pt = pt.GetElementType(); if (svcMthPrm.IsIn) { pfx = "ref "; } else { pfx = "out "; } } bool nullable; var ptName = pt.GetTypeNameSave(out nullable); if (nullable) { ptName = ptName + "?"; } if (svcMthPrm.IsOptional) { //were implementing the interface "as it is" string defaultValueString = ""; if (svcMthPrm.DefaultValue == null) { defaultValueString = " = null"; } else if (svcMthPrm.DefaultValue.GetType() == typeof(string)) { defaultValueString = " = \"" + svcMthPrm.DefaultValue.ToString() + "\""; } else { defaultValueString = " = " + svcMthPrm.DefaultValue.ToString() + ""; } paramSignature.Add($"{pfx}{ptName} {svcMthPrm.Name}" + defaultValueString); //paramSignature.Add($"{pt} {svcMthPrm.Name} = default({ptName})"); //if (pt.IsValueType) { // paramSignature.Add($"{pfx}{ptName}? {svcMthPrm.Name} = null"); //} //else { // paramSignature.Add($"{pfx}{ptName} {svcMthPrm.Name} = null"); //} } else { paramSignature.Add($"{pfx}{ptName} {svcMthPrm.Name}"); } } if (svcMth.ReturnType == null || svcMth.ReturnType == typeof(void)) { writer.WriteLineAndPush($"public void {svcMth.Name}({String.Join(", ", paramSignature.ToArray())}) {{"); } else { writer.WriteLineAndPush($"public {svcMth.ReturnType.Name} {svcMth.Name}({String.Join(", ", paramSignature.ToArray())}) {{"); } writer.WriteLineAndPush($"using (var webClient = this.CreateWebClient()) {{"); writer.WriteLine($"string url = _Url + \"{writer.Ftl(svcMth.Name)}\";"); writer.WriteLineAndPush($"var args = new {svcMth.Name}Request {{"); int i = 0; int pCount = svcMth.GetParameters().Length; foreach (ParameterInfo svcMthPrm in svcMth.GetParameters()) { if (!svcMthPrm.IsOut) { i++; if (i < pCount) { writer.WriteLine($"{svcMthPrm.Name} = {svcMthPrm.Name},"); } else { writer.WriteLine($"{svcMthPrm.Name} = {svcMthPrm.Name}"); } } } writer.PopAndWriteLine("};"); writer.WriteLine($"string rawRequest = JsonConvert.SerializeObject(args);"); writer.WriteLine($"string rawResponse = webClient.UploadString(url, rawRequest);"); writer.WriteLine($"var result = JsonConvert.DeserializeObject<{svcMth.Name}Response>(rawResponse);"); foreach (ParameterInfo svcMthPrm in svcMth.GetParameters()) { if (svcMthPrm.IsOut) { writer.WriteLine($"{svcMthPrm.Name} = result.{svcMthPrm.Name};"); } } if (cfg.throwClientExecptionsFromFaultProperty) { writer.WriteLineAndPush($"if(result.fault != null){{"); writer.WriteLine($"throw new Exception(result.fault);"); writer.PopAndWriteLine("}"); } if (svcMth.ReturnType == null || svcMth.ReturnType == typeof(void)) { writer.WriteLine($"return;"); } else { writer.WriteLine($"return result.@return;"); } writer.PopAndWriteLine("}"); //using writer.PopAndWriteLine("}"); //method }//foreach Method writer.WriteLine(); writer.PopAndWriteLine("}"); //class }//foreach Interface if (!String.IsNullOrWhiteSpace(cfg.outputNamespace)) { writer.WriteLine(); writer.WriteEndNamespace(); } }
public void Generate(CodeWriterBase writer, Cfg cfg) { if (writer.GetType() != typeof(WriterForCS)) { throw new Exception("For the selected template is currenty only language 'CS' supported!"); } var nsImports = new List <string>(); nsImports.Add("Microsoft.AspNetCore.Mvc"); nsImports.Add("Microsoft.Extensions.Logging"); nsImports.Add("Security"); if (cfg.generateSwashbuckleAttributesForControllers) { nsImports.Add("Swashbuckle.AspNetCore.Annotations"); } nsImports.Add("System"); nsImports.Add("System.Collections.Generic"); nsImports.Add("System.Linq"); nsImports.Add("System.Net"); var inputFileFullPath = Path.GetFullPath(cfg.inputFile); Program.AddResolvePath(Path.GetDirectoryName(inputFileFullPath)); Assembly ass = Assembly.LoadFile(inputFileFullPath); Type[] svcInterfaces; try { svcInterfaces = ass.GetTypes(); } catch (ReflectionTypeLoadException ex) { svcInterfaces = ex.Types.Where((t) => t != null).ToArray(); } //transform patterns to regex cfg.interfaceTypeNamePattern = "^(" + Regex.Escape(cfg.interfaceTypeNamePattern).Replace("\\*", ".*?") + ")$"; svcInterfaces = svcInterfaces.Where((Type i) => Regex.IsMatch(i.FullName, cfg.interfaceTypeNamePattern)).ToArray(); if (!String.IsNullOrWhiteSpace(cfg.outputNamespace) && cfg.customImports.Contains(cfg.outputNamespace)) { nsImports.Remove(cfg.outputNamespace); } foreach (string import in cfg.customImports.Union(nsImports).Distinct().OrderBy((s) => s)) { writer.WriteImport(import); } if (!String.IsNullOrWhiteSpace(cfg.outputNamespace)) { writer.WriteLine(); writer.WriteBeginNamespace(cfg.outputNamespace); } //collect models //var directlyUsedModelTypes = new List<Type>(); //var wrappers = new Dictionary<String, StringBuilder>(); foreach (Type svcInt in svcInterfaces) { //if(!nsImports.Contains(svcInt.Namespace)){ // nsImports.Add(svcInt.Namespace); //} string svcIntDoc = XmlCommentAccessExtensions.GetDocumentation(svcInt); string endpointName = svcInt.Name; if (endpointName[0] == 'I' && Char.IsUpper(endpointName[1])) { endpointName = endpointName.Substring(1); } writer.WriteLine(); writer.WriteLine("[ApiController]"); writer.WriteLine($"[Route(\"{writer.Ftl(endpointName)}\")]"); writer.WriteLineAndPush($"public partial class {endpointName}Controller : ControllerBase {{"); writer.WriteLine(); writer.WriteLine($"private readonly ILogger<{endpointName}Controller> _Logger;"); writer.WriteLine($"private readonly {svcInt.Name} _{endpointName};"); writer.WriteLine(); writer.WriteLineAndPush($"public {endpointName}Controller(ILogger<{endpointName}Controller> logger, {svcInt.Name} {writer.Ftl(endpointName)}) {{"); writer.WriteLine($"_Logger = logger;"); writer.WriteLine($"_{endpointName} = {writer.Ftl(endpointName)};"); writer.PopAndWriteLine("}"); foreach (MethodInfo svcMth in svcInt.GetMethods()) { string svcMthDoc = XmlCommentAccessExtensions.GetDocumentation(svcMth, true); writer.WriteLine(); if (String.IsNullOrWhiteSpace(svcMthDoc)) { svcMthDoc = svcMth.Name; } writer.WriteLine($"/// <summary> {svcMthDoc} </summary>"); writer.WriteLine($"/// <param name=\"args\"> request capsule containing the method arguments </param>"); if (!String.IsNullOrWhiteSpace(cfg.customAttributesPerControllerMethod)) { writer.WriteLine("[" + cfg.customAttributesPerControllerMethod.Replace("{C}", endpointName).Replace("{O}", svcMth.Name) + "]"); } writer.WriteLine($"[HttpPost(\"{writer.Ftl(svcMth.Name)}\"), Produces(\"application/json\")]"); string swaggerBodyAttrib = ""; if (cfg.generateSwashbuckleAttributesForControllers) { swaggerBodyAttrib = "[SwaggerRequestBody(Required = true)]"; string escDesc = svcMthDoc.Replace("\\", "\\\\").Replace("\"", "\\\""); nsImports.Add($"[SwaggerOperation(OperationId = nameof({svcMth.Name}), Description = \"{escDesc}\")]"); } writer.WriteLineAndPush($"public {svcMth.Name}Response {svcMth.Name}([FromBody]{swaggerBodyAttrib} {svcMth.Name}Request args) {{"); writer.WriteLineAndPush("try {"); writer.WriteLine($"var response = new {svcMth.Name}Response();"); var @params = new List <string>(); foreach (ParameterInfo svcMthPrm in svcMth.GetParameters()) { if (svcMthPrm.IsOut) { if (svcMthPrm.IsIn) { writer.WriteLine($"response.{writer.Ftl(svcMthPrm.Name)} = args.{writer.Ftl(svcMthPrm.Name)}; //shift IN-OUT value"); } @params.Add($"response.{writer.Ftl(svcMthPrm.Name)}"); } else { if (svcMthPrm.IsOptional) { string defaultValueString = ""; if (svcMthPrm.DefaultValue == null) { defaultValueString = "null"; } else if (svcMthPrm.DefaultValue.GetType() == typeof(string)) { defaultValueString = "\"" + svcMthPrm.DefaultValue.ToString() + "\""; } else { defaultValueString = svcMthPrm.DefaultValue.ToString(); } if (svcMthPrm.ParameterType.IsValueType) { @params.Add($"(args.{writer.Ftl(svcMthPrm.Name)}.HasValue ? args.{writer.Ftl(svcMthPrm.Name)}.Value : {defaultValueString})"); } else { //here 'null' will be used @params.Add($"args.{writer.Ftl(svcMthPrm.Name)}"); //@params.Add($"(args.{writer.Ftl(svcMthPrm.Name)} == null ? args.{writer.Ftl(svcMthPrm.Name)} : {defaultValueString})"); } } else { @params.Add($"args.{writer.Ftl(svcMthPrm.Name)}"); } } } if (svcMth.ReturnType != null && svcMth.ReturnType != typeof(void)) { writer.WriteLine($"response.@return = _{endpointName}.{svcMth.Name}({Environment.NewLine + String.Join("," + Environment.NewLine, @params.ToArray()) + Environment.NewLine});"); } else { writer.WriteLine($"_{endpointName}.{svcMth.Name}({Environment.NewLine + String.Join("," + Environment.NewLine, @params.ToArray()) + Environment.NewLine});"); } writer.WriteLine($"return response;"); writer.PopAndWriteLine("}"); writer.WriteLineAndPush("catch (Exception ex) {"); writer.WriteLine($"_Logger.LogCritical(ex, ex.Message);"); if (cfg.fillFaultPropertyOnException) { writer.WriteLine($"return new {svcMth.Name}Response {{ fault = {cfg.exceptionDisplay} }};"); } else { writer.WriteLine($"return new {svcMth.Name}Response();"); } writer.PopAndWriteLine("}"); writer.PopAndWriteLine("}"); //method }//foreach Method writer.WriteLine(); writer.PopAndWriteLine("}"); //controller-class }//foreach Interface if (!String.IsNullOrWhiteSpace(cfg.outputNamespace)) { writer.WriteLine(); writer.WriteEndNamespace(); } }