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("System");
            nsImports.Add("System.Collections.Generic");
            nsImports.Add("System.ComponentModel.DataAnnotations");

            var wrapperContent = new StringBuilder(10000);

            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();

            //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);

                foreach (MethodInfo svcMth in svcInt.GetMethods())
                {
                    string svcMthDoc = XmlCommentAccessExtensions.GetDocumentation(svcMth, false);

                    if (svcMth.ReturnType != null && svcMth.ReturnType != typeof(void))
                    {
                        //directlyUsedModelTypes.Add(svcMth.ReturnType);
                        if (!nsImports.Contains(svcMth.ReturnType.Namespace))
                        {
                            nsImports.Add(svcMth.ReturnType.Namespace);
                        }
                    }

                    string        requestWrapperName     = svcMth.Name + "Request";
                    string        responseWrapperName    = svcMth.Name + "Response";
                    StringBuilder requestWrapperContent  = new StringBuilder(500);
                    StringBuilder responseWrapperContent = new StringBuilder(500);

                    requestWrapperContent.AppendLine();
                    requestWrapperContent.AppendLine("/// <summary>");
                    requestWrapperContent.AppendLine($"/// Contains arguments for calling '{svcMth.Name}'.");
                    if (!String.IsNullOrWhiteSpace(svcMthDoc))
                    {
                        requestWrapperContent.AppendLine($"/// Method: " + svcMthDoc.Replace("\n", "\n///   "));
                    }
                    requestWrapperContent.AppendLine("/// </summary>");
                    requestWrapperContent.AppendLine("public class " + requestWrapperName + " {");

                    responseWrapperContent.AppendLine();
                    responseWrapperContent.AppendLine("/// <summary>");
                    responseWrapperContent.AppendLine($"/// Contains results from calling '{svcMth.Name}'.");
                    if (!String.IsNullOrWhiteSpace(svcMthDoc))
                    {
                        responseWrapperContent.AppendLine($"/// Method: " + svcMthDoc.Replace("\n", "\n///   "));
                    }
                    responseWrapperContent.AppendLine("/// </summary>");
                    responseWrapperContent.AppendLine("public class " + responseWrapperName + " {");

                    foreach (ParameterInfo svcMthPrm in svcMth.GetParameters())
                    {
                        string svcMthPrmDoc = XmlCommentAccessExtensions.GetDocumentation(svcMthPrm);
                        if (String.IsNullOrWhiteSpace(svcMthPrmDoc))
                        {
                            svcMthPrmDoc = XmlCommentAccessExtensions.GetDocumentation(svcMthPrm.ParameterType);
                        }
                        //directlyUsedModelTypes.Add(svcMthPrm.ParameterType);

                        if (!nsImports.Contains(svcMthPrm.ParameterType.Namespace))
                        {
                            nsImports.Add(svcMthPrm.ParameterType.Namespace);
                        }

                        string reqStr = "Required";
                        if (svcMthPrm.IsOptional)
                        {
                            reqStr = "Optional";
                        }


                        //if (svcMthPrm.IsOptional) {
                        //  //paramSignature.Add($"{pt} {svcMthPrm.Name} = default({pt.Name})");
                        //  if (pt.IsValueType) {
                        //    paramSignature.Add($"{pfx}{pt.Name}? {svcMthPrm.Name} = null");
                        //  }
                        //  else {
                        //    paramSignature.Add($"{pfx}{pt.Name} {svcMthPrm.Name} = null");
                        //  }
                        //}
                        //else {
                        //  paramSignature.Add($"{pfx}{pt.Name} {svcMthPrm.Name}");
                        //}

                        //string accessModifier = "";//interfaces have no a.m.
                        //if (modelTypeToGenerate.IsClass) {
                        //  accessModifier = "public ";
                        //}
                        //string pType = prop.PropertyType.Name;
                        //if ()

                        String pType;
                        String initializer = "";

                        bool nullable;
                        if (svcMthPrm.IsOut)
                        {
                            pType = svcMthPrm.ParameterType.GetElementType().GetTypeNameSave(out nullable);
                        }
                        else
                        {
                            pType = svcMthPrm.ParameterType.GetTypeNameSave(out nullable);
                        }
                        if (nullable || (svcMthPrm.IsOptional && svcMthPrm.ParameterType.IsValueType))
                        {
                            pType       = pType + "?";
                            initializer = " = null;";
                        }

                        if (!svcMthPrm.IsOut)
                        {
                            requestWrapperContent.AppendLine();
                            if (!String.IsNullOrWhiteSpace(svcMthPrmDoc))
                            {
                                requestWrapperContent.AppendLine($"  /// <summary> {reqStr} Argument for '{svcMth.Name}' ({pType}): {svcMthPrmDoc} </summary>");
                            }
                            else
                            {
                                requestWrapperContent.AppendLine($"  /// <summary> {reqStr} Argument for '{svcMth.Name}' ({pType}) </summary>");
                            }
                            if (!svcMthPrm.IsOptional)
                            {
                                requestWrapperContent.AppendLine("  [Required]");
                            }
                            requestWrapperContent.AppendLine("  public " + pType + " " + svcMthPrm.Name + " { get; set; }" + initializer);
                        }
                        if (svcMthPrm.IsOut)
                        {
                            responseWrapperContent.AppendLine();
                            if (!String.IsNullOrWhiteSpace(svcMthPrmDoc))
                            {
                                responseWrapperContent.AppendLine($"  /// <summary> Out-Argument of '{svcMth.Name}' ({pType}): {svcMthPrmDoc} </summary>");
                            }
                            else
                            {
                                responseWrapperContent.AppendLine($"  /// <summary> Out-Argument of '{svcMth.Name}' ({pType}) </summary>");
                            }
                            if (!svcMthPrm.IsOptional)
                            {
                                responseWrapperContent.AppendLine("  [Required]");
                            }
                            responseWrapperContent.AppendLine("  public " + pType + " " + svcMthPrm.Name + " { get; set; }" + initializer);
                        }
                    }//foreach Param

                    if (cfg.generateFaultProperty)
                    {
                        responseWrapperContent.AppendLine();
                        responseWrapperContent.AppendLine($"  /// <summary> This field contains error text equivalent to an Exception message! (note that only 'fault' XOR 'return' can have a value != null)  </summary>");
                        responseWrapperContent.AppendLine("  public string fault { get; set; } = null;");
                    }

                    requestWrapperContent.AppendLine();
                    requestWrapperContent.AppendLine("}");

                    if (svcMth.ReturnType != null && svcMth.ReturnType != typeof(void))
                    {
                        responseWrapperContent.AppendLine();
                        string retTypeDoc = XmlCommentAccessExtensions.GetDocumentation(svcMth.ReturnType);
                        if (!String.IsNullOrWhiteSpace(retTypeDoc))
                        {
                            responseWrapperContent.AppendLine($"  /// <summary> Return-Value of '{svcMth.Name}' ({svcMth.ReturnType.Name}): {retTypeDoc} </summary>");
                        }
                        else
                        {
                            responseWrapperContent.AppendLine($"  /// <summary> Return-Value of '{svcMth.Name}' ({svcMth.ReturnType.Name}) </summary>");
                        }
                        if (!cfg.generateFaultProperty)
                        {
                            responseWrapperContent.AppendLine("  [Required]");
                        }
                        responseWrapperContent.AppendLine("  public " + svcMth.ReturnType.Name + " @return { get; set; }");
                    }
                    responseWrapperContent.AppendLine();
                    responseWrapperContent.AppendLine("}");

                    wrapperContent.Append(requestWrapperContent);
                    wrapperContent.Append(responseWrapperContent);
                } //foreach Method
            }     //foreach Interface

            //this can be done only here, because the nsImports will be extended during main-logic
            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);
            }

            using (var sr = new StringReader(wrapperContent.ToString())) {
                string line = sr.ReadLine();
                while (line != null)
                {
                    writer.WriteLine(line);
                    line = sr.ReadLine();
                }
            }

            if (!String.IsNullOrWhiteSpace(cfg.outputNamespace))
            {
                writer.WriteLine();
                writer.WriteEndNamespace();
            }
        }
Example #2
0
        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();
            }
        }
Example #3
0
        public void Generate(CodeWriterBase writer, Cfg cfg)
        {
            if (writer.GetType() != typeof(WriterForCS))
            {
                throw new Exception("For the selected template is currenty only language 'C#' supported!");
            }

            var nsImports = new List <string>();

            nsImports.Add("System");
            nsImports.Add("System.Collections.Generic");

            if (cfg.generateNavigationAnnotationsForLocalModels)
            {
                nsImports.Add("System.ComponentModel.DataAnnotations"); //+ extended by the "EntityAnnoations" Nuget Package!
            }
            else if (cfg.generateDataAnnotationsForLocalModels)
            {
                nsImports.Add("System.ComponentModel.DataAnnotations");
            }

            var modelContent = new StringBuilder(10000);

            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("\\*", ".*?") + ")$";
            for (int i = 0; i < cfg.modelTypeNameIncludePatterns.Length; i++)
            {
                cfg.modelTypeNameIncludePatterns[i] = "^(" + Regex.Escape(cfg.modelTypeNameIncludePatterns[i]).Replace("\\*", ".*?") + ")$";
            }

            svcInterfaces = svcInterfaces.Where((Type i) => Regex.IsMatch(i.FullName, cfg.interfaceTypeNamePattern)).ToArray();

            //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);

                foreach (MethodInfo svcMth in svcInt.GetMethods())
                {
                    string svcMthDoc = XmlCommentAccessExtensions.GetDocumentation(svcMth, false);

                    if (svcMth.ReturnType != null && svcMth.ReturnType != typeof(void))
                    {
                        directlyUsedModelTypes.Add(svcMth.ReturnType);
                        if (!nsImports.Contains(svcMth.ReturnType.Namespace))
                        {
                            nsImports.Add(svcMth.ReturnType.Namespace);
                        }
                    }

                    foreach (ParameterInfo svcMthPrm in svcMth.GetParameters())
                    {
                        string svcMthPrmDoc = XmlCommentAccessExtensions.GetDocumentation(svcMthPrm);
                        if (String.IsNullOrWhiteSpace(svcMthPrmDoc))
                        {
                            svcMthPrmDoc = XmlCommentAccessExtensions.GetDocumentation(svcMthPrm.ParameterType);
                        }
                        directlyUsedModelTypes.Add(svcMthPrm.ParameterType);

                        if (!nsImports.Contains(svcMthPrm.ParameterType.Namespace))
                        {
                            nsImports.Add(svcMthPrm.ParameterType.Namespace);
                        }
                    } //foreach Param
                }     //foreach Method
            }         //foreach Interface

            Action <List <Type>, Type> addRecursiveMethod = null;

            addRecursiveMethod = (collector, candidate) => {
                if (candidate.IsArray)
                {
                    candidate = candidate.GetElementType();
                }
                else if (candidate.IsGenericType)
                {
                    var genBase = candidate.GetGenericTypeDefinition();
                    var genArg1 = candidate.GetGenericArguments()[0];
                    if (typeof(List <>).MakeGenericType(genArg1).IsAssignableFrom(candidate))
                    {
                        candidate = genArg1;
                    }
                    else if (typeof(Collection <>).MakeGenericType(genArg1).IsAssignableFrom(candidate))
                    {
                        candidate = genArg1;
                    }
                    if (genBase == typeof(Nullable <>))
                    {
                        candidate = genArg1;
                    }
                }

                if (!collector.Contains(candidate))
                {
                    bool match = false;
                    for (int i = 0; i < cfg.modelTypeNameIncludePatterns.Length; i++)
                    {
                        if (Regex.IsMatch(candidate.FullName, cfg.modelTypeNameIncludePatterns[i]))
                        {
                            match = true;
                            break;
                        }
                    }
                    if (match)
                    {
                        collector.Add(candidate);
                        if (candidate.BaseType != null)
                        {
                            addRecursiveMethod.Invoke(collector, candidate.BaseType);
                        }
                        foreach (PropertyInfo p in candidate.GetProperties())
                        {
                            addRecursiveMethod.Invoke(collector, p.PropertyType);
                        }
                    }
                }
            };

            var modelTypesToGenerate = new List <Type>();

            foreach (Type canidate in directlyUsedModelTypes.Distinct())
            {
                addRecursiveMethod.Invoke(modelTypesToGenerate, canidate);
            }

            foreach (Type modelTypeToGenerate in modelTypesToGenerate.OrderBy((m) => m.Name))
            {
                string modelDoc = XmlCommentAccessExtensions.GetDocumentation(modelTypeToGenerate, true);

                modelContent.AppendLine();

                if (!String.IsNullOrWhiteSpace(modelDoc))
                {
                    modelContent.AppendLine($"/// <summary>");
                    modelContent.AppendLine($"/// " + modelDoc.Replace("\n", "\n/// "));
                    modelContent.AppendLine($"/// </summary>");
                }

                //TODO: Obsolete-Attributes on Class-Level (including comments)

                if (modelTypeToGenerate.IsClass)
                {
                    modelContent.Append("public class " + modelTypeToGenerate.Name);
                }
                else
                {
                    modelContent.Append("public interface " + modelTypeToGenerate.Name);
                }

                if (modelTypeToGenerate.BaseType != null)
                {
                    modelContent.AppendLine(" {");
                }
                else
                {
                    modelContent.AppendLine(" : " + modelTypeToGenerate.BaseType.Name + " {");
                }

                foreach (PropertyInfo prop in modelTypeToGenerate.GetProperties())
                {
                    string propDoc = XmlCommentAccessExtensions.GetDocumentation(prop, true);

                    modelContent.AppendLine();

                    if (!String.IsNullOrWhiteSpace(propDoc))
                    {
                        modelContent.AppendLine($"  /// <summary>");
                        modelContent.AppendLine($"  /// " + propDoc.Replace("\n", "\n  /// "));
                        modelContent.AppendLine($"  /// </summary>");
                    }

                    var attribs = prop.GetCustomAttributes();

                    if (cfg.generateDataAnnotationsForLocalModels)
                    {
                        if (prop.GetCustomAttributes <RequiredAttribute>().Any())
                        {
                            modelContent.AppendLine("  [Required]");
                        }
                        ObsoleteAttribute oa = prop.GetCustomAttributes <ObsoleteAttribute>().FirstOrDefault();
                        if (oa != null)
                        {
                            modelContent.AppendLine("  [Obsolete(\"" + oa.Message + "\")]");
                        }
                        MaxLengthAttribute mla = prop.GetCustomAttributes <MaxLengthAttribute>().FirstOrDefault();
                        if (mla != null)
                        {
                            modelContent.AppendLine("  [MaxLength(" + mla.Length.ToString() + ")]");
                        }
                    }

                    if (cfg.generateNavigationAnnotationsForLocalModels)
                    {
                        //here we use strings, because we dont want to have a reference to a nuget-pkg within this template
                        if (attribs.Where((a) => a.GetType().Name == "FixedAfterCreationAttribute").Any())
                        {
                            modelContent.AppendLine("  [FixedAfterCreation]");
                        }
                        if (attribs.Where((a) => a.GetType().Name == "SystemInternalAttribute").Any())
                        {
                            modelContent.AppendLine("  [SystemInternal]");
                        }
                        if (attribs.Where((a) => a.GetType().Name == "LookupAttribute").Any())
                        {
                            modelContent.AppendLine("  [Lookup]");
                        }
                        if (attribs.Where((a) => a.GetType().Name == "RefererAttribute").Any())
                        {
                            modelContent.AppendLine("  [Referer]");
                        }
                        if (attribs.Where((a) => a.GetType().Name == "PrincipalAttribute").Any())
                        {
                            modelContent.AppendLine("  [Principal]");
                        }
                        if (attribs.Where((a) => a.GetType().Name == "DependentAttribute").Any())
                        {
                            modelContent.AppendLine("  [Dependent]");
                        }
                    }

                    string accessModifier = "";//interfaces have no a.m.
                    if (modelTypeToGenerate.IsClass)
                    {
                        accessModifier = "public ";
                    }

                    modelContent.AppendLine($"  " + accessModifier + prop.PropertyType.Name + " " + prop.Name + " { get; set; }");
                }

                modelContent.AppendLine();
                modelContent.AppendLine("}");
                modelContent.AppendLine();
            }

            //this can be done only here, because the nsImports will be extended during main-logic
            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);
            }

            using (var sr = new StringReader(modelContent.ToString())) {
                string line = sr.ReadLine();
                while (line != null)
                {
                    writer.WriteLine(line);
                    line = sr.ReadLine();
                }
            }

            if (!String.IsNullOrWhiteSpace(cfg.outputNamespace))
            {
                writer.WriteEndNamespace();
            }
        }
Example #4
0
        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();
            }
        }