Skip to content

Commit 7f9398a

Browse files
committed
Initial commit for DWB customization
1 parent f735c6e commit 7f9398a

13 files changed

Lines changed: 595 additions & 55 deletions

modules/openapi-generator/src/main/resources/csharp/libraries/generichost/ClientUtils.mustache

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,14 @@ using System.Runtime.CompilerServices;
209209
entries.Add(ParameterToString(entry));
210210
return string.Join(",", entries);
211211
}
212+
// DNV customization: Add parameter type IEnumerable
213+
else if (obj is IEnumerable enumerable)
214+
{
215+
List<string{{nrt?}}> entries = new{{^net70OrLater}} List<string{{nrt?}}>{{/net70OrLater}}();
216+
foreach (var entry in enumerable)
217+
entries.Add(ParameterToString(entry));
218+
return string.Join(",", entries);
219+
}
212220

213221
return Convert.ToString(obj, System.Globalization.CultureInfo.InvariantCulture);
214222
}

modules/openapi-generator/src/main/resources/csharp/libraries/generichost/DateOnlyJsonConverter.mustache

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,8 @@ namespace {{packageName}}.{{clientPackage}}
3333
string value = reader.GetString(){{nrt!}};
3434

3535
foreach(string format in Formats)
36-
if (DateOnly.TryParseExact(value, format, CultureInfo.InvariantCulture, DateTimeStyles.AdjustToUniversal | DateTimeStyles.AssumeUniversal, out DateOnly result))
36+
// DNV customization: DateOnly is irrelevant to time zone.
37+
if (DateOnly.TryParseExact(value, format, CultureInfo.InvariantCulture, DateTimeStyles.None, out DateOnly result))
3738
return result;
3839

3940
throw new NotSupportedException();

modules/openapi-generator/src/main/resources/csharp/libraries/generichost/DateOnlyNullableJsonConverter.mustache

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,8 @@ namespace {{packageName}}.{{clientPackage}}
3333
string value = reader.GetString(){{nrt!}};
3434

3535
foreach(string format in Formats)
36-
if (DateOnly.TryParseExact(value, format, CultureInfo.InvariantCulture, DateTimeStyles.AdjustToUniversal | DateTimeStyles.AssumeUniversal, out DateOnly result))
36+
// DNV customization: DateOnly is irrelevant to time zone.
37+
if (DateOnly.TryParseExact(value, format, CultureInfo.InvariantCulture, DateTimeStyles.None, out DateOnly result))
3738
return result;
3839

3940
throw new NotSupportedException();

modules/openapi-generator/src/main/resources/csharp/libraries/generichost/HostConfiguration.mustache

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ using {{packageName}}.{{apiPackage}};
1616
using {{packageName}}.{{modelPackage}};
1717
{{/-first}}
1818
{{/models}}
19+
using System.Text.Json.Serialization.Metadata;
1920

2021
namespace {{packageName}}.{{clientPackage}}
2122
{
@@ -54,6 +55,8 @@ namespace {{packageName}}.{{clientPackage}}
5455
{{/isEnum}}
5556
{{/model}}
5657
{{/models}}
58+
// DNV customization: Use default resolver to support AOT
59+
_jsonOptions.TypeInfoResolver = new DefaultJsonTypeInfoResolver();
5760
JsonSerializerOptionsProvider jsonSerializerOptionsProvider = new{{^net60OrLater}} JsonSerializerOptionsProvider{{/net60OrLater}}(_jsonOptions);
5861
_services.AddSingleton(jsonSerializerOptionsProvider);
5962
{{#useSourceGeneration}}
@@ -82,6 +85,8 @@ namespace {{packageName}}.{{clientPackage}}
8285
_services.AddSingleton<IApiFactory, ApiFactory>();{{#apiInfo}}{{#apis}}
8386
_services.AddSingleton<{{classname}}Events>();
8487
_services.AddTransient<{{interfacePrefix}}{{classname}}, {{classname}}>();{{/apis}}{{/apiInfo}}
88+
// DNV customization: Inject client name.
89+
_services.AddTransient<{{interfacePrefix}}{{clientName}}, {{clientName}}>();
8590
}
8691

8792
/// <summary>
@@ -101,6 +106,7 @@ namespace {{packageName}}.{{clientPackage}}
101106
102107
{{#apiInfo}}{{#apis}}builders.Add(_services.AddHttpClient<{{interfacePrefix}}{{classname}}, {{classname}}>(client));
103108
{{/apis}}{{/apiInfo}}
109+
builders.Add(_services.AddHttpClient<{{interfacePrefix}}{{clientName}}, {{clientName}}>(client));
104110
if (builder != null)
105111
foreach (IHttpClientBuilder instance in builders)
106112
builder(instance);

modules/openapi-generator/src/main/resources/csharp/libraries/generichost/IApi.mustache

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,13 @@
1+
using System;
2+
using System.Collections.Generic;
13
using System.Net.Http;
4+
using System.Text.Json;
5+
using System.Text.Json.Serialization;
6+
using System.Text.Json.Serialization.Metadata;
7+
using Microsoft.Extensions.Logging;
8+
using {{packageName}}.{{clientPackage}};
9+
using {{packageName}}.{{apiPackage}};
10+
using {{packageName}}.{{modelPackage}};
211

312
namespace {{packageName}}.{{apiPackage}}
413
{
@@ -12,4 +21,68 @@ namespace {{packageName}}.{{apiPackage}}
1221
/// </summary>
1322
HttpClient HttpClient { get; }
1423
}
24+
25+
// DNV customization: Add client interface/object
26+
/// <summary>
27+
/// </summary>
28+
public partial interface {{interfacePrefix}}{{clientName}}
29+
{
30+
JsonSerializerOptionsProvider JsonSerializerOptionsProvider { get; }
31+
32+
{{#apiInfo.apis}}
33+
{{interfacePrefix}}{{classname}} {{classname}} { get; }
34+
{{/apiInfo.apis}}
35+
36+
}
37+
}
38+
39+
namespace {{packageName}}
40+
{
41+
public class {{clientName}} : {{interfacePrefix}}{{clientName}}
42+
{
43+
public HttpClient HttpClient { get; }
44+
public JsonSerializerOptionsProvider JsonSerializerOptionsProvider { get; private set; }
45+
{{#apiInfo.apis}}
46+
{{>visibility}} virtual {{interfacePrefix}}{{classname}} {{classname}} { get; private set; }
47+
{{/apiInfo.apis}}
48+
49+
public {{clientName}}(
50+
HttpClient httpClient, bool dummy = true, JsonSerializerOptionsProvider? jsonSerializerOptionsProvider = null)
51+
{
52+
HttpClient = httpClient;
53+
if (jsonSerializerOptionsProvider != null)
54+
{
55+
JsonSerializerOptionsProvider = jsonSerializerOptionsProvider;
56+
}
57+
else
58+
{
59+
var jsonSerializerOptions = new JsonSerializerOptions();
60+
jsonSerializerOptions.Converters.Add(new JsonStringEnumConverter());
61+
jsonSerializerOptions.Converters.Add(new DateTimeJsonConverter());
62+
jsonSerializerOptions.Converters.Add(new DateTimeNullableJsonConverter());
63+
{{#supportsDateOnly}}
64+
jsonSerializerOptions.Converters.Add(new DateOnlyJsonConverter());
65+
jsonSerializerOptions.Converters.Add(new DateOnlyNullableJsonConverter());
66+
{{/supportsDateOnly}}
67+
{{#models}}
68+
{{#model}}
69+
{{#isEnum}}
70+
jsonSerializerOptions.Converters.Add(new {{datatypeWithEnum}}{{^datatypeWithEnum}}{{classname}}{{/datatypeWithEnum}}JsonConverter());
71+
jsonSerializerOptions.Converters.Add(new {{datatypeWithEnum}}{{^datatypeWithEnum}}{{classname}}{{/datatypeWithEnum}}NullableJsonConverter());
72+
{{/isEnum}}
73+
{{^isEnum}}
74+
jsonSerializerOptions.Converters.Add(new {{classname}}JsonConverter());
75+
{{/isEnum}}
76+
{{/model}}
77+
{{/models}}
78+
jsonSerializerOptions.TypeInfoResolver = new DefaultJsonTypeInfoResolver();
79+
JsonSerializerOptionsProvider = new JsonSerializerOptionsProvider(jsonSerializerOptions);
80+
}
81+
var loggerFactory = LoggerFactory.Create(builder => builder.AddConsole().SetMinimumLevel(LogLevel.Information));
82+
{{#apiInfo.apis}}
83+
{{classname}} = new {{classname}}(loggerFactory.CreateLogger<{{classname}}>(), loggerFactory, httpClient, JsonSerializerOptionsProvider, new {{classname}}Events());
84+
{{/apiInfo.apis}}
85+
}
86+
87+
}
1588
}

modules/openapi-generator/src/main/resources/csharp/libraries/generichost/JsonConverter.mustache

Lines changed: 30 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -225,20 +225,40 @@
225225
{{/isDateTime}}
226226
{{#isEnum}}
227227
{{^isMap}}
228-
{{#isNumeric}}
229-
{{#lambda.camelcase_sanitize_param}}{{name}}{{/lambda.camelcase_sanitize_param}} = {{>OptionProperty}}utf8JsonReader.TokenType == JsonTokenType.Null ? ({{#isInnerEnum}}{{classname}}.{{/isInnerEnum}}{{{datatypeWithEnum}}}?)null : ({{#isInnerEnum}}{{classname}}.{{/isInnerEnum}}{{{datatypeWithEnum}}})utf8JsonReader.Get{{#vendorExtensions.x-unsigned}}U{{/vendorExtensions.x-unsigned}}Int32());
230-
{{/isNumeric}}
228+
// DNV customization: Handle enum by value
229+
/*
230+
"EnumByValue": {
231+
"enum": [
232+
100,
233+
200
234+
],
235+
"type": "integer",
236+
"format": "int32",
237+
"x-enum-descriptions": [
238+
"",
239+
""
240+
],
241+
"x-enum-varnames": [
242+
"A",
243+
"B"
244+
],
245+
"description": "\n\n100 - A\n\n200 - B"
246+
},*/
247+
{{#allowableValues}}{{#enumVars}}{{#-first}}{{#isString}}
231248
{{^isNumeric}}
232-
string{{nrt?}} {{#lambda.camelcase_sanitize_param}}{{name}}{{/lambda.camelcase_sanitize_param}}RawValue = utf8JsonReader.GetString();
249+
string{{nrt?}} {{#lambda.camelcase_sanitize_param}}{{baseName}}{{/lambda.camelcase_sanitize_param}}RawValue = utf8JsonReader.GetString();
233250
{{^isInnerEnum}}
234-
if ({{#lambda.camelcase_sanitize_param}}{{name}}{{/lambda.camelcase_sanitize_param}}RawValue != null)
235-
{{#lambda.camelcase_sanitize_param}}{{name}}{{/lambda.camelcase_sanitize_param}} = {{>OptionProperty}}{{{datatypeWithEnum}}}ValueConverter.FromStringOrDefault({{#lambda.camelcase_sanitize_param}}{{name}}{{/lambda.camelcase_sanitize_param}}RawValue));
251+
if ({{#lambda.camelcase_sanitize_param}}{{baseName}}{{/lambda.camelcase_sanitize_param}}RawValue != null)
252+
{{#lambda.camelcase_sanitize_param}}{{baseName}}{{/lambda.camelcase_sanitize_param}} = {{>OptionProperty}}{{{datatypeWithEnum}}}ValueConverter.FromStringOrDefault({{#lambda.camelcase_sanitize_param}}{{baseName}}{{/lambda.camelcase_sanitize_param}}RawValue));
236253
{{/isInnerEnum}}
237254
{{#isInnerEnum}}
238-
if ({{#lambda.camelcase_sanitize_param}}{{name}}{{/lambda.camelcase_sanitize_param}}RawValue != null)
239-
{{#lambda.camelcase_sanitize_param}}{{name}}{{/lambda.camelcase_sanitize_param}} = {{>OptionProperty}}{{classname}}.{{{datatypeWithEnum}}}FromStringOrDefault({{#lambda.camelcase_sanitize_param}}{{name}}{{/lambda.camelcase_sanitize_param}}RawValue));
255+
if ({{#lambda.camelcase_sanitize_param}}{{baseName}}{{/lambda.camelcase_sanitize_param}}RawValue != null)
256+
{{#lambda.camelcase_sanitize_param}}{{baseName}}{{/lambda.camelcase_sanitize_param}} = {{>OptionProperty}}{{classname}}.{{{datatypeWithEnum}}}FromStringOrDefault({{#lambda.camelcase_sanitize_param}}{{baseName}}{{/lambda.camelcase_sanitize_param}}RawValue));
240257
{{/isInnerEnum}}
241258
{{/isNumeric}}
259+
{{/isString}}{{#isNumeric}}
260+
{{#lambda.camelcase_sanitize_param}}{{baseName}}{{/lambda.camelcase_sanitize_param}} = {{>OptionProperty}}utf8JsonReader.TokenType == JsonTokenType.Null ? ({{#isInnerEnum}}{{classname}}.{{/isInnerEnum}}{{{datatypeWithEnum}}}?)null : ({{#isInnerEnum}}{{classname}}.{{/isInnerEnum}}{{{datatypeWithEnum}}})utf8JsonReader.Get{{#vendorExtensions.x-unsigned}}U{{/vendorExtensions.x-unsigned}}Int32());
261+
{{/isNumeric}}{{/-first}}{{/enumVars}}{{/allowableValues}}
242262
{{/isMap}}
243263
{{/isEnum}}
244264
{{#isUuid}}
@@ -338,9 +358,7 @@
338358
public override void Write(Utf8JsonWriter writer, {{classname}} {{#lambda.camelcase_sanitize_param}}{{classname}}{{/lambda.camelcase_sanitize_param}}, JsonSerializerOptions jsonSerializerOptions)
339359
{
340360
{{#lambda.trimLineBreaks}}
341-
{{#lambda.copyText}}
342-
{{#lambda.camelcase_sanitize_param}}{{classname}}{{/lambda.camelcase_sanitize_param}}
343-
{{/lambda.copyText}}
361+
{{#lambda.copyText}}{{#lambda.camelcase_sanitize_param}}{{classname}}{{/lambda.camelcase_sanitize_param}}{{/lambda.copyText}}
344362
{{#discriminator}}
345363
{{#children}}
346364
if ({{#lambda.paste}}{{/lambda.paste}} is {{classname}} {{#lambda.camelcase_sanitize_param}}{{classname}}{{/lambda.camelcase_sanitize_param}}){
@@ -520,9 +538,7 @@
520538
{{/isNullable}}
521539
{{/isInnerEnum}}
522540
{{^isInnerEnum}}
523-
{{#lambda.copyText}}
524-
{{#lambda.camelcase_sanitize_param}}{{name}}{{/lambda.camelcase_sanitize_param}}
525-
{{/lambda.copyText}}
541+
{{#lambda.copyText}}{{#lambda.camelcase_sanitize_param}}{{name}}{{/lambda.camelcase_sanitize_param}}{{/lambda.copyText}}
526542
{{#required}}
527543
{{#isNullable}}
528544
if ({{#lambda.camelcase_sanitize_param}}{{classname}}{{/lambda.camelcase_sanitize_param}}.{{name}} == null)

modules/openapi-generator/src/main/resources/csharp/libraries/generichost/Option.mustache

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,11 @@ namespace {{packageName}}.{{clientPackage}}
2828
/// <param name="value"></param>
2929
public Option(TType value)
3030
{
31-
IsSet = true;
32-
Value = value;
31+
if (value != null)
32+
{
33+
IsSet = true;
34+
Value = value;
35+
}
3336
}
3437

3538
/// <summary>

modules/openapi-generator/src/main/resources/csharp/libraries/generichost/README.client.mustache

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -50,9 +50,8 @@ using System;
5050
using System.Threading.Tasks;
5151
using Microsoft.Extensions.Hosting;
5252
using Microsoft.Extensions.DependencyInjection;
53-
using {{packageName}}.Api;
54-
using {{packageName}}.Client;
55-
using {{packageName}}.Model;
53+
using {{packageName}}.Extensions;
54+
using {{packageName}}.Interfaces;
5655

5756
namespace YourProject
5857
{
@@ -61,13 +60,13 @@ namespace YourProject
6160
public static async Task Main(string[] args)
6261
{
6362
var host = CreateHostBuilder(args).Build();{{#apiInfo}}{{#apis}}{{#-first}}
64-
var api = host.Services.GetRequiredService<{{interfacePrefix}}{{classname}}>();
63+
var api = host.Services.GetRequiredService<{{interfacePrefix}}{{clientName}}>();
6564
{{#operations}}
6665
{{#-first}}
6766
{{#operation}}
6867
{{#-first}}
69-
{{operationId}}ApiResponse apiResponse = await api.{{operationId}}Async("todo");
70-
{{#returnType}}{{{.}}}{{/returnType}}{{^returnType}}object{{/returnType}} model = apiResponse.Ok();
68+
var apiResponse = await api.{{baseName}}.{{#vendorExtensions.x-csharp-operationId}}{{vendorExtensions.x-csharp-operationId}}{{/vendorExtensions.x-csharp-operationId}}{{^vendorExtensions.x-csharp-operationId}}{{operationId}}{{/vendorExtensions.x-csharp-operationId}}Async("todo");
69+
Console.WriteLine($"Response: {apiResponse.ToString()}");
7170
{{/-first}}
7271
{{/operation}}
7372
{{/-first}}
@@ -78,7 +77,7 @@ namespace YourProject
7877
}
7978

8079
public static IHostBuilder CreateHostBuilder(string[] args) => Host.CreateDefaultBuilder(args)
81-
.Configure{{apiName}}((context, options) =>
80+
.Configure{{apiName}}((context, services, options) =>
8281
{
8382
{{#authMethods}}
8483
{{#-first}}
@@ -96,7 +95,9 @@ namespace YourProject
9695
// your custom converters if any
9796
});
9897

99-
options.Add{{apiName}}HttpClients(builder: builder => builder
98+
options.Add{{apiName}}HttpClients(
99+
client: client => client.BaseAddress = new Uri(context.Configuration["ApiSettings:BaseAddress"]),
100+
builder: builder => builder
100101
.AddRetryPolicy(2)
101102
.AddTimeoutPolicy(TimeSpan.FromSeconds(5))
102103
.AddCircuitBreakerPolicy(10, TimeSpan.FromSeconds(30))
@@ -138,7 +139,7 @@ All URIs are relative to *{{{basePath}}}*
138139

139140
Class | Method | HTTP request | Description
140141
------------ | ------------- | ------------- | -------------{{#apiInfo}}{{#apis}}{{#operations}}{{#operation}}
141-
*{{classname}}* | [**{{operationId}}**]({{apiDocPath}}{{classname}}.md#{{operationIdLowerCase}}) | **{{httpMethod}}** {{path}} | {{#summary}}{{{summary}}}{{/summary}}{{/operation}}{{/operations}}{{/apis}}{{/apiInfo}}{{/apiDocs}}{{#modelDocs}}
142+
*{{classname}}* | [**{{#vendorExtensions.x-csharp-operationId}}{{vendorExtensions.x-csharp-operationId}}{{/vendorExtensions.x-csharp-operationId}}{{^vendorExtensions.x-csharp-operationId}}{{operationId}}{{/vendorExtensions.x-csharp-operationId}}**]({{apiDocPath}}{{classname}}.md#{{operationIdLowerCase}}) | **{{httpMethod}}** {{path}} | {{#summary}}{{{summary}}}{{/summary}}{{/operation}}{{/operations}}{{/apis}}{{/apiInfo}}{{/apiDocs}}{{#modelDocs}}
142143

143144
<a id="documentation-for-models"></a>
144145
## Documentation for Models

0 commit comments

Comments
 (0)