diff --git a/.idea/.idea.MakeGenericAgain/.idea/.gitignore b/.idea/.idea.MakeGenericAgain/.idea/.gitignore
new file mode 100644
index 0000000..c69e223
--- /dev/null
+++ b/.idea/.idea.MakeGenericAgain/.idea/.gitignore
@@ -0,0 +1,15 @@
+# Default ignored files
+/shelf/
+/workspace.xml
+# Rider ignored files
+/projectSettingsUpdater.xml
+/modules.xml
+/.idea.MakeGenericAgain.iml
+/contentModel.xml
+# Editor-based HTTP Client requests
+/httpRequests/
+# Ignored default folder with query files
+/queries/
+# Datasource local storage ignored files
+/dataSources/
+/dataSources.local.xml
diff --git a/.idea/.idea.MakeGenericAgain/.idea/encodings.xml b/.idea/.idea.MakeGenericAgain/.idea/encodings.xml
new file mode 100644
index 0000000..df87cf9
--- /dev/null
+++ b/.idea/.idea.MakeGenericAgain/.idea/encodings.xml
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/.idea/.idea.MakeGenericAgain/.idea/indexLayout.xml b/.idea/.idea.MakeGenericAgain/.idea/indexLayout.xml
new file mode 100644
index 0000000..7b08163
--- /dev/null
+++ b/.idea/.idea.MakeGenericAgain/.idea/indexLayout.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/.idea.MakeGenericAgain/.idea/vcs.xml b/.idea/.idea.MakeGenericAgain/.idea/vcs.xml
new file mode 100644
index 0000000..35eb1dd
--- /dev/null
+++ b/.idea/.idea.MakeGenericAgain/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/MakeGenericAgain/CommandLineArgs.cs b/MakeGenericAgain/CommandLineArgs.cs
index 076288e..00d5c05 100644
--- a/MakeGenericAgain/CommandLineArgs.cs
+++ b/MakeGenericAgain/CommandLineArgs.cs
@@ -1,77 +1,79 @@
-using System;
-using System.Collections;
-using System.Collections.Generic;
-using System.Linq;
-using System.Reflection;
+namespace MakeGenericAgain;
-namespace MakeGenericAgain
+public static class CommandLineArgs
{
- public static class CommandLineArgs
+ public static T Parse(string[] args)
+ where T : new()
+ => Parse(string.Join(" ", args));
+
+ public static T Parse(string args)
+ where T : new()
{
- public static T Parse(string[] args) where T : new()
- {
- return Parse(string.Join(" ", args));
- }
+ T res = new();
+ PropertyInfo[] props = typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance);
- public static T Parse(string args) where T : new()
+ foreach (PropertyInfo prop in props)
{
- var res = new T();
- var props = typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance);
+ IEnumerable namesForProp = (prop.GetCustomAttribute()?.ParamNames.Select(s => s.EnsureStartsWith("-").ToLower()) ?? [])
+ .Concat([
+ "-" + prop.Name.ToLower()
+ ])
+ .Distinct();
- foreach (var prop in props)
+ foreach (string name in namesForProp)
{
- var namesForProp = (prop.GetCustomAttribute()?.ParamNames.Select(s => s.EnsureStartsWith("-").ToLower()) ?? Enumerable.Empty())
- .Concat(new[] { "-" + prop.Name.ToLower() })
- .Distinct();
+ int indexOf = args.IndexOf(name + "=", StringComparison.Ordinal);
+
+ if (indexOf < 0)
+ indexOf = args.IndexOf(name + " ", StringComparison.Ordinal);
+
+ if (indexOf < 0)
+ continue;
+
+ int startOfValue = indexOf + name.Length;
+ if (args[startOfValue] == '=')
+ startOfValue++;
+
+ int endOfValue = args.IndexOf(" -", startOfValue, StringComparison.Ordinal);
+ if (endOfValue == -1)
+ endOfValue = args.Length;
+
+ string value = args.Substring(startOfValue, endOfValue - startOfValue).Trim();
+
+ if (value.StartsWith("\"") && value.EndsWith("\""))
+ value = value[1..^1];
- foreach (var name in namesForProp)
+ if (IsCollection(prop))
{
- var indexOf = args.IndexOf(name + "=", StringComparison.Ordinal);
- if (indexOf < 0) indexOf = args.IndexOf(name + " ", StringComparison.Ordinal);
- if (indexOf < 0) continue;
-
- var startOfValue = indexOf + name.Length;
- if (args[startOfValue] == '=') startOfValue++;
-
- var endOfValue = args.IndexOf(" -", startOfValue, StringComparison.Ordinal);
- if (endOfValue == -1) endOfValue = args.Length;
-
- var value = args.Substring(startOfValue, endOfValue - startOfValue).Trim();
-
- if (value.StartsWith("\"") && value.EndsWith("\""))
- {
- value = value[1..^1];
- }
-
- if (IsCollection(prop))
- {
- var values = value.Split(',')
- .Select(v => v.Trim())
- .Where(v => !string.IsNullOrEmpty(v))
- .ToArray();
- prop.SetValue(res, values);
- }
- else
- {
- prop.SetValue(res, value);
- }
+ string[] values = value.Split(',')
+ .Select(v => v.Trim())
+ .Where(v => !string.IsNullOrEmpty(v))
+ .ToArray();
+
+ prop.SetValue(res, values);
+ }
+ else
+ {
+ prop.SetValue(res, value);
}
}
- return res;
}
+ return res;
+ }
- private static string EnsureStartsWith(this string str, string toStartWith)
- {
- if (!str.StartsWith(toStartWith))
- str = toStartWith + str;
- return str;
- }
+ public static bool IsCollection(this Type type)
+ => type.IsGenericType && type.GetGenericTypeDefinition() == typeof(ICollection<>) || type.IsGenericType && type.GetGenericTypeDefinition() == typeof(IEnumerable<>) ||
+ typeof(IEnumerable).IsAssignableFrom(type) && type != typeof(string) || type.IsArray || type.GetInterfaces().Any(IsCollection);
- private static bool IsCollection(PropertyInfo prop)
- => prop.PropertyType != typeof(string) && prop.PropertyType.IsCollection();
+ private static string EnsureStartsWith(this string str, string toStartWith)
+ {
+ if (!str.StartsWith(toStartWith))
+ str = toStartWith + str;
- public static bool IsCollection(this Type type)
- => type.IsGenericType && type.GetGenericTypeDefinition() == typeof(ICollection<>) || type.IsGenericType && type.GetGenericTypeDefinition() == typeof(IEnumerable<>) || typeof(IEnumerable).IsAssignableFrom(type) && type != typeof(string) || type.IsArray || type.GetInterfaces().Any(IsCollection);
+ return str;
}
+
+ private static bool IsCollection(PropertyInfo prop)
+ => prop.PropertyType != typeof(string) && prop.PropertyType.IsCollection();
}
\ No newline at end of file
diff --git a/MakeGenericAgain/FromCommandLineAttribute.cs b/MakeGenericAgain/FromCommandLineAttribute.cs
index 3584c2d..9d3bbf3 100644
--- a/MakeGenericAgain/FromCommandLineAttribute.cs
+++ b/MakeGenericAgain/FromCommandLineAttribute.cs
@@ -1,15 +1,10 @@
-using System;
+namespace MakeGenericAgain;
-namespace MakeGenericAgain
+[AttributeUsage(AttributeTargets.Property, AllowMultiple = true)]
+public class FromCommandLineAttribute : Attribute
{
- [AttributeUsage(AttributeTargets.Property, AllowMultiple = true)]
- public class FromCommandLineAttribute: Attribute
- {
- public FromCommandLineAttribute(params string[] paramNames)
- {
- ParamNames = paramNames;
- }
+ public FromCommandLineAttribute(params string[] paramNames)
+ => ParamNames = paramNames;
- public string[] ParamNames { get; set; }
- }
+ public string[] ParamNames { get; set; }
}
\ No newline at end of file
diff --git a/MakeGenericAgain/GlobalUsings.cs b/MakeGenericAgain/GlobalUsings.cs
new file mode 100644
index 0000000..ef3ba0c
--- /dev/null
+++ b/MakeGenericAgain/GlobalUsings.cs
@@ -0,0 +1,7 @@
+global using System;
+global using System.Collections;
+global using System.Collections.Generic;
+global using System.IO;
+global using System.Linq;
+global using System.Reflection;
+global using System.Text.RegularExpressions;
\ No newline at end of file
diff --git a/MakeGenericAgain/MakeGenericAgain.csproj b/MakeGenericAgain/MakeGenericAgain.csproj
index e71ed32..123ef2f 100644
--- a/MakeGenericAgain/MakeGenericAgain.csproj
+++ b/MakeGenericAgain/MakeGenericAgain.csproj
@@ -1,37 +1,37 @@
-
- Exe
- net6.0;net8.0
- latest
- true
- makeGenericAgain
- ./nupkg
- 1.0.5
- Florian Gilde
- MakeGenericAgain
- 0.0.0-dev
- Git
- true
-
- Problem is that nswag client code generation from open api specification or swagger generates classes without generics. This tool can be used afterwards to make classes generic again
-
-
- https://github.com/fgilde/MakeGenericAgain
- Copyright © $(Authors) 2020-$([System.DateTime]::Now.Year)
- MIT
- README.md
-
+
+ Exe
+ net6.0;net8.0;net10.0
+ latest
+ true
+ makeGenericAgain
+ ./nupkg
+ 1.0.7
+ Florian Gilde
+ MakeGenericAgain
+ 0.0.0-dev
+ Git
+ true
+
+ Problem is that nswag client code generation from open api specification or swagger generates classes without generics. This tool can be used afterwards to make classes generic again
+
-
-
- all
- runtime; build; native; contentfiles; analyzers; buildtransitive
-
-
+ https://github.com/fgilde/MakeGenericAgain
+ Copyright © $(Authors) 2020-$([System.DateTime]::Now.Year)
+ MIT
+ README.md
+
-
-
-
+
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
+
+
+
+
+
diff --git a/MakeGenericAgain/NameReplacer.cs b/MakeGenericAgain/NameReplacer.cs
index fd0add0..fda91ea 100644
--- a/MakeGenericAgain/NameReplacer.cs
+++ b/MakeGenericAgain/NameReplacer.cs
@@ -1,63 +1,57 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text.RegularExpressions;
+namespace MakeGenericAgain;
-namespace MakeGenericAgain
+public static class NameReplacer
{
- public static class NameReplacer
+ public static string ReplaceToGeneric(string str, ICollection typesToIgnore)
{
- public static string ReplaceToGeneric(string str, ICollection typesToIgnore)
- {
- var toSplit = Regex.Replace(str, @"[^\w\.@-]", " ", RegexOptions.None, TimeSpan.FromSeconds(1.5)).Replace(".", " ");
- foreach (var word in toSplit.Split(" "))
- {
- // ignore any types provided in options
- if (typesToIgnore.Contains(word))
- continue;
-
- if (word.Contains("Of") && !word.StartsWith("Of") && !word.EndsWith("Of") && !word.StartsWith("DateTime"))
- {
- var genericWordFor = GetGenericWordFor(word);
- if (word != genericWordFor)
- str = str.Replace(word, genericWordFor);
- }
- }
-
- return str;
- }
+ string toSplit = Regex.Replace(str, @"[^\w\.@-]", " ", RegexOptions.None, TimeSpan.FromSeconds(1.5)).Replace(".", " ");
- internal static string GetGenericWordFor(string word)
+ foreach (string word in toSplit.Split(" "))
{
- var parts = word.Split("Of");
+ // ignore any types provided in options
+ if (typesToIgnore.Contains(word))
+ continue;
- var closing = string.Join("",Enumerable.Repeat(">", parts.Length - 1));
- var opening = string.Join("", parts.Select((p,i) => i < parts.Length - 1 ? $"{TypeNameFor(p)}<" : TypeNameFor(p)));
- var result = opening + closing;
+ if (!word.Contains("Of") || word.StartsWith("Of") || word.EndsWith("Of") || word.StartsWith("DateTime"))
+ continue;
- return result;
+ string genericWordFor = GetGenericWordFor(word);
+ if (word != genericWordFor)
+ str = str.Replace(word, genericWordFor);
}
- private static string TypeNameFor(string type)
+ return str;
+ }
+
+ internal static string GetGenericWordFor(string word)
+ {
+ string[] parts = word.Split("Of");
+
+ string closing = string.Join("", Enumerable.Repeat(">", parts.Length - 1));
+
+ string opening = string.Join("", parts.Select((p, i) => i < parts.Length - 1
+ ? $"{TypeNameFor(p)}<"
+ : TypeNameFor(p)));
+
+ string result = opening + closing;
+
+ return result;
+ }
+
+ private static string TypeNameFor(string type)
+ {
+ if (type.Contains("And"))
+ return string.Join(",", type.Split("And").Select(TypeNameFor));
+
+ return type switch
{
- if (type.Contains("And"))
- {
- return string.Join(",", type.Split("And").Select(TypeNameFor));
- }
-
- if (type == "Integer")
- return "int";
- if (type == "String")
- return "string";
- if (type == "Boolean" || type == "Bool")
- return "bool";
- if (type == "Double")
- return "double";
- if (type == "Float")
- return "float";
- if (type == "Decimal")
- return "decimal";
- return type;
- }
+ "Integer" => "int",
+ "String" => "string",
+ "Boolean" or "Bool" => "bool",
+ "Double" => "double",
+ "Float" => "float",
+ "Decimal" => "decimal",
+ _ => type
+ };
}
}
\ No newline at end of file
diff --git a/MakeGenericAgain/Options.cs b/MakeGenericAgain/Options.cs
index 7f2c77b..6fbb86d 100644
--- a/MakeGenericAgain/Options.cs
+++ b/MakeGenericAgain/Options.cs
@@ -1,16 +1,13 @@
-using System.Collections.Generic;
+namespace MakeGenericAgain;
-namespace MakeGenericAgain
+public class Options
{
- public class Options
- {
- [FromCommandLine("f", nameof(FileName))]
- public string FileName { get; set; }
+ [FromCommandLine("f", nameof(FileName))]
+ public string FileName { get; set; }
- [FromCommandLine("o", nameof(OutputFileName))]
- public string OutputFileName { get; set; }
+ [FromCommandLine("o", nameof(OutputFileName))]
+ public string OutputFileName { get; set; }
- [FromCommandLine("i", nameof(TypesToIgnore))]
- public ICollection TypesToIgnore { get; set; } = [];
- }
+ [FromCommandLine("i", nameof(TypesToIgnore))]
+ public ICollection TypesToIgnore { get; set; } = [];
}
\ No newline at end of file
diff --git a/MakeGenericAgain/Program.cs b/MakeGenericAgain/Program.cs
index f85b404..ffd5573 100644
--- a/MakeGenericAgain/Program.cs
+++ b/MakeGenericAgain/Program.cs
@@ -1,55 +1,54 @@
-using System;
-using System.IO;
+namespace MakeGenericAgain;
-namespace MakeGenericAgain
+internal class Program
{
- class Program
+ private static Options _options;
+
+ private static int Main(string[] args)
{
- private static Options options;
- static int Main(string[] args)
- {
- options = CommandLineArgs.Parse(args);
- return (int)Handle();
- }
+ _options = CommandLineArgs.Parse(args);
+ return (int)Handle();
+ }
- static ExitCode Handle()
+ private static ExitCode Handle()
+ {
+ try
{
- try
- {
- if (string.IsNullOrEmpty(options.FileName) || !File.Exists(options.FileName))
- {
- return Return(ExitCode.InvalidFilename, $"Error Filename '{options.FileName}' is invalid or not existing");
- }
-
- var lines = File.ReadAllLines(options.FileName);
- for (var index = 0; index < lines.Length; index++)
- {
- lines[index] = NameReplacer.ReplaceToGeneric(lines[index], options.TypesToIgnore);
- }
- File.WriteAllLines(options.OutputFileName ?? options.FileName, lines);
- return Return(ExitCode.Success, $"Filename {options.FileName} has successfully been updated");
- }
- catch (Exception e)
- {
- return Return(ExitCode.UnknownError, e.Message);
- }
- }
+ if (string.IsNullOrEmpty(_options.FileName) || !File.Exists(_options.FileName))
+ return Return(ExitCode.InvalidFilename, $"Error Filename '{_options.FileName}' is invalid or not existing");
+
+ string[] lines = File.ReadAllLines(_options.FileName);
+ for (int index = 0; index < lines.Length; index++)
+ lines[index] = NameReplacer.ReplaceToGeneric(lines[index], _options.TypesToIgnore);
+
+ File.WriteAllLines(_options.OutputFileName ?? _options.FileName, lines);
- static ExitCode Return (ExitCode code, string message)
+ return Return(ExitCode.Success, $"Filename {_options.FileName} has successfully been updated");
+ }
+ catch (Exception e)
{
- var color = Console.ForegroundColor;
- Console.ForegroundColor = code == ExitCode.Success ? ConsoleColor.Green : ConsoleColor.Red;
- Console.WriteLine(message);
- Console.ForegroundColor = color;
- return code;
+ return Return(ExitCode.UnknownError, e.Message);
}
-
}
- enum ExitCode : int
+ private static ExitCode Return(ExitCode code, string message)
{
- Success = 0,
- InvalidFilename = 1,
- UnknownError = 2
+ ConsoleColor color = Console.ForegroundColor;
+
+ Console.ForegroundColor = code == ExitCode.Success
+ ? ConsoleColor.Green
+ : ConsoleColor.Red;
+
+ Console.WriteLine(message);
+ Console.ForegroundColor = color;
+
+ return code;
}
}
+
+internal enum ExitCode
+{
+ Success = 0,
+ InvalidFilename = 1,
+ UnknownError = 2
+}
\ No newline at end of file
diff --git a/README.md b/README.md
index 42f3f34..45255a2 100644
--- a/README.md
+++ b/README.md
@@ -1,10 +1,12 @@
# MakeGenericAgain
-Problem is that nswag client code generation from open api specification or swagger generates classes without generics. This tool can be used afterwards to make classes generic again
+
+Problem is that nswag client code generation from open api specification or swagger generates classes without generics.
+This tool can be used afterwards to make classes generic again
More infos about the general problem can be found here
- - https://github.com/RicoSuter/NSwag/issues/1139
- - https://blog.devgenius.io/nswag-csharp-client-with-generics-support-6ad6a09f81d6
+- https://github.com/RicoSuter/NSwag/issues/1139
+- https://blog.devgenius.io/nswag-csharp-client-with-generics-support-6ad6a09f81d6
To install it on other projects, add this to the csproj:
@@ -15,7 +17,8 @@ To install it on other projects, add this to the csproj:
```
-You can optionally provide names of types to ignore (should include any type names containing the word 'Of' as a minimum)
+You can optionally provide names of types to ignore (should include any type names containing the word 'Of' as a
+minimum)
```
@@ -25,6 +28,7 @@ You can optionally provide names of types to ignore (should include any type nam
```
To run int use
+
```
makeGenericAgain -f "C:\Path\client.cs"
```
@@ -36,13 +40,14 @@ Or with ignorable type names
```
Also you can specify specific output file with -o
+
```
makeGenericAgain -f "C:\Path\client.cs" -i "IgnorableOfType,AnotherOfIgnorable" -o "C:\Path\client_with_generics.cs"
```
-
-
## Links
-[Github Repository](https://github.com/fgilde/MakeGenericAgain) |
+
+[Github Repository](https://github.com/fgilde/MakeGenericAgain) |
[Nuget Package](https://www.nuget.org/packages/MakeGenericAgain/)
-#
\ No newline at end of file
+
+#
diff --git a/version.json b/version.json
index 74dd9db..78da150 100644
--- a/version.json
+++ b/version.json
@@ -1,17 +1,17 @@
{
- "$schema": "https://raw.githubusercontent.com/dotnet/Nerdbank.GitVersioning/master/src/NerdBank.GitVersioning/version.schema.json",
- "version": "1.0.6",
- "cloudBuild": {
- "buildNumber": {
- "enabled": true,
- "setVersionVariables": true,
- "includeCommitId": {
- "when": "nonPublicReleaseOnly",
- "where": "buildMetadata"
- }
- }
- },
- "publicReleaseRefSpec": [
- "^refs/heads/main$"
- ]
+ "$schema": "https://raw.githubusercontent.com/dotnet/Nerdbank.GitVersioning/master/src/NerdBank.GitVersioning/version.schema.json",
+ "version": "1.0.7",
+ "cloudBuild": {
+ "buildNumber": {
+ "enabled": true,
+ "setVersionVariables": true,
+ "includeCommitId": {
+ "when": "nonPublicReleaseOnly",
+ "where": "buildMetadata"
+ }
+ }
+ },
+ "publicReleaseRefSpec": [
+ "^refs/heads/main$"
+ ]
}