@@ -14,6 +14,146 @@ internal static partial class TestHelpers
1414 public static readonly string GENERATED_CODE = "[System.CodeDom.Compiler.GeneratedCode(\" NJsonSchema\" , \" " + APICODEGEN_VERSION + "\" )]" ;
1515 public static readonly string GENERATED_CODE_ATTRIBUTE = "[System.CodeDom.Compiler.GeneratedCode(\" ApiCodeGenerator.AsyncApi\" , \" " + APICODEGEN_VERSION + "\" )]" ;
1616
17+ public static readonly string JSON_INHERITANCE_CONVERTER = $$ """
18+ {{ GENERATED_CODE }}
19+ [System.AttributeUsage(System.AttributeTargets.Class | System.AttributeTargets.Interface, AllowMultiple = true)]
20+ internal class JsonInheritanceAttribute : System.Attribute
21+ {
22+ public JsonInheritanceAttribute(string key, System.Type type)
23+ {
24+ Key = key;
25+ Type = type;
26+ }
27+
28+ public string Key { get; }
29+
30+ public System.Type Type { get; }
31+ }
32+
33+ {{ GENERATED_CODE }}
34+ public class JsonInheritanceConverter : Newtonsoft.Json.JsonConverter
35+ {
36+ internal static readonly string DefaultDiscriminatorName = "discriminator";
37+
38+ private readonly string _discriminatorName;
39+
40+ [System.ThreadStatic]
41+ private static bool _isReading;
42+
43+ [System.ThreadStatic]
44+ private static bool _isWriting;
45+
46+ public JsonInheritanceConverter()
47+ {
48+ _discriminatorName = DefaultDiscriminatorName;
49+ }
50+
51+ public JsonInheritanceConverter(string discriminatorName)
52+ {
53+ _discriminatorName = discriminatorName;
54+ }
55+
56+ public string DiscriminatorName { get { return _discriminatorName; } }
57+
58+ public override void WriteJson(Newtonsoft.Json.JsonWriter writer, object value, Newtonsoft.Json.JsonSerializer serializer)
59+ {
60+ try
61+ {
62+ _isWriting = true;
63+
64+ var jObject = Newtonsoft.Json.Linq.JObject.FromObject(value, serializer);
65+ jObject.AddFirst(new Newtonsoft.Json.Linq.JProperty(_discriminatorName, GetSubtypeDiscriminator(value.GetType())));
66+ writer.WriteToken(jObject.CreateReader());
67+ }
68+ finally
69+ {
70+ _isWriting = false;
71+ }
72+ }
73+
74+ public override bool CanWrite
75+ {
76+ get
77+ {
78+ if (_isWriting)
79+ {
80+ _isWriting = false;
81+ return false;
82+ }
83+ return true;
84+ }
85+ }
86+
87+ public override bool CanRead
88+ {
89+ get
90+ {
91+ if (_isReading)
92+ {
93+ _isReading = false;
94+ return false;
95+ }
96+ return true;
97+ }
98+ }
99+
100+ public override bool CanConvert(System.Type objectType)
101+ {
102+ return true;
103+ }
104+
105+ public override object ReadJson(Newtonsoft.Json.JsonReader reader, System.Type objectType, object existingValue, Newtonsoft.Json.JsonSerializer serializer)
106+ {
107+ var jObject = serializer.Deserialize<Newtonsoft.Json.Linq.JObject>(reader);
108+ if (jObject == null)
109+ return null;
110+
111+ var discriminatorValue = jObject.GetValue(_discriminatorName);
112+ var discriminator = discriminatorValue != null ? Newtonsoft.Json.Linq.Extensions.Value<string>(discriminatorValue) : null;
113+ var subtype = GetObjectSubtype(objectType, discriminator);
114+
115+ var objectContract = serializer.ContractResolver.ResolveContract(subtype) as Newtonsoft.Json.Serialization.JsonObjectContract;
116+ if (objectContract == null || System.Linq.Enumerable.All(objectContract.Properties, p => p.PropertyName != _discriminatorName))
117+ {
118+ jObject.Remove(_discriminatorName);
119+ }
120+
121+ try
122+ {
123+ _isReading = true;
124+ return serializer.Deserialize(jObject.CreateReader(), subtype);
125+ }
126+ finally
127+ {
128+ _isReading = false;
129+ }
130+ }
131+
132+ private System.Type GetObjectSubtype(System.Type objectType, string discriminator)
133+ {
134+ foreach (var attribute in System.Reflection.CustomAttributeExtensions.GetCustomAttributes<JsonInheritanceAttribute>(System.Reflection.IntrospectionExtensions.GetTypeInfo(objectType), true))
135+ {
136+ if (attribute.Key == discriminator)
137+ return attribute.Type;
138+ }
139+
140+ return objectType;
141+ }
142+
143+ private string GetSubtypeDiscriminator(System.Type objectType)
144+ {
145+ foreach (var attribute in System.Reflection.CustomAttributeExtensions.GetCustomAttributes<JsonInheritanceAttribute>(System.Reflection.IntrospectionExtensions.GetTypeInfo(objectType), true))
146+ {
147+ if (attribute.Type == objectType)
148+ return attribute.Key;
149+ }
150+
151+ return objectType.Name;
152+ }
153+ }
154+
155+ """ . Replace ( "\r " , string . Empty ) ;
156+
17157 public static string GetAsyncApiPath ( string schemaFile ) => Path . Combine ( "asyncApi" , schemaFile ) ;
18158
19159 public static async Task < TextReader > LoadApiDocumentAsync ( string fileName )
@@ -41,10 +181,9 @@ public static async Task RunTest(CSharpClientGeneratorSettings settings, string
41181 Assert . That ( actual , Is . EqualTo ( expected ) ) ;
42182 }
43183
44- public static GeneratorContext CreateContext ( string settingsJson , string schemaFile , Core . ExtensionManager . Extensions ? extensions = null )
184+ public static GeneratorContext CreateContext ( string settingsJson , TextReader docReader , Core . ExtensionManager . Extensions ? extensions = null )
45185 {
46186 var jReader = new JsonTextReader ( new StringReader ( settingsJson ) ) ;
47- var docReader = File . OpenText ( GetAsyncApiPath ( schemaFile ) ) ;
48187
49188 return new GeneratorContext (
50189 ( t , s , v ) => s ! . Deserialize ( jReader , t ) ,
@@ -55,6 +194,9 @@ public static GeneratorContext CreateContext(string settingsJson, string schemaF
55194 } ;
56195 }
57196
197+ public static GeneratorContext CreateContext ( string settingsJson , string schemaFile , Core . ExtensionManager . Extensions ? extensions = null )
198+ => CreateContext ( settingsJson , File . OpenText ( GetAsyncApiPath ( schemaFile ) ) , extensions ) ;
199+
58200 public static string GetExpectedCode ( string ? expectedClientDeclartion , string ? testOperResponseText , string @namespace = "TestNS" , string ? usings = null )
59201 {
60202 if ( ! string . IsNullOrWhiteSpace ( expectedClientDeclartion ) && ! expectedClientDeclartion . Contains ( GENERATED_CODE_ATTRIBUTE ) )
0 commit comments