diff --git a/bin/csharp-dotnet2-petstore.sh b/bin/csharp-dotnet2-petstore.sh old mode 100755 new mode 100644 diff --git a/bin/security/windows/csharp-petstore.bat b/bin/security/windows/csharp-petstore.bat new file mode 100644 index 00000000000..2bb9ba99d00 --- /dev/null +++ b/bin/security/windows/csharp-petstore.bat @@ -0,0 +1,10 @@ +set executable=.\modules\swagger-codegen-cli\target\swagger-codegen-cli.jar + +If Not Exist %executable% ( + mvn clean package +) + +REM set JAVA_OPTS=%JAVA_OPTS% -Xmx1024M +set ags=generate -i modules/swagger-codegen/src/test/resources/2_0/petstore-security-test.yaml -l csharp -o samples/client/petstore-security-test/csharp/SwaggerClient --additional-properties packageGuid={8CE139DF-64BC-4591-85F8-8506C2B67514} + +java %JAVA_OPTS% -jar %executable% %ags% diff --git a/bin/windows/csharp-dotnet2-petstore.bat b/bin/windows/csharp-dotnet2-petstore.bat new file mode 100755 index 00000000000..b321637d386 --- /dev/null +++ b/bin/windows/csharp-dotnet2-petstore.bat @@ -0,0 +1,10 @@ +set executable=.\modules\swagger-codegen-cli\target\swagger-codegen-cli.jar + +If Not Exist %executable% ( + mvn clean package +) + +REM set JAVA_OPTS=%JAVA_OPTS% -Xmx1024M +set ags=generate -i modules/swagger-codegen/src/test/resources/2_0/petstore.yaml -l CsharpDotNet2 -o samples/client/petstore/csharp-dotnet2/SwaggerClientTest/Lib/SwaggerClient --additional-properties hideGenerationTimestamp=true + +java %JAVA_OPTS% -jar %executable% %ags% diff --git a/bin/windows/csharp-petstore-all.bat b/bin/windows/csharp-petstore-all.bat index ecef022653a..f68f9283e62 100755 --- a/bin/windows/csharp-petstore-all.bat +++ b/bin/windows/csharp-petstore-all.bat @@ -1,8 +1,14 @@ REM C# Petstore API client -.\bin\windows\csharp-petstore.bat +call .\bin\windows\csharp-petstore.bat REM C# Petstore API client with PropertyChanged -.\bin\windows\csharp-property-changed-petstore.bat +call .\bin\windows\csharp-property-changed-petstore.bat REM C# Petstore API client (v5.0 for .net standarnd 1.3+) -.\bin\windows\csharp-petstore-netstandard.bat +call .\bin\windows\csharp-petstore-netstandard.bat + +call .\bin\windows\csharp-dotnet2-petstore.bat + +call .\bin\windows\csharp-petstore-netcore-project.bat + +call .\bin\windows\csharp-property-changed-petstore.bat \ No newline at end of file diff --git a/bin/windows/csharp-property-changed-petstore.bat b/bin/windows/csharp-property-changed-petstore.bat index 4e92f348a49..a09f557def3 100644 --- a/bin/windows/csharp-property-changed-petstore.bat +++ b/bin/windows/csharp-property-changed-petstore.bat @@ -5,6 +5,6 @@ If Not Exist %executable% ( ) REM set JAVA_OPTS=%JAVA_OPTS% -Xmx1024M -set ags=generate -i modules/swagger-codegen/src/test/resources/2_0/petstore-with-fake-endpoints-models-for-testing.yaml -l csharp -o samples\client\petstore\csharp\SwaggerClientNetStandard --additional-properties targetFramework=v5.0,packageGuid={3AB1F259-1769-484B-9411-84505FCCBD55} +set ags=generate -i modules/swagger-codegen/src/test/resources/2_0/petstore-with-fake-endpoints-models-for-testing.yaml -l csharp -o samples\client\petstore\csharp\SwaggerClientWithPropertyChanged --additional-properties=generatePropertyChanged=true,packageGuid={5CD900DE-8266-412F-A758-28E1F9C623D5} java %JAVA_OPTS% -jar %executable% %ags% diff --git a/modules/swagger-codegen/src/main/java/io/swagger/codegen/DefaultCodegen.java b/modules/swagger-codegen/src/main/java/io/swagger/codegen/DefaultCodegen.java index 3bd8e2e9041..3be5473c050 100644 --- a/modules/swagger-codegen/src/main/java/io/swagger/codegen/DefaultCodegen.java +++ b/modules/swagger-codegen/src/main/java/io/swagger/codegen/DefaultCodegen.java @@ -3159,6 +3159,7 @@ public class DefaultCodegen { if (Boolean.TRUE.equals(cp.isReadOnly)) { m.readOnlyVars.add(cp); } else { // else add to readWriteVars (list of properties) + // FIXME: readWriteVars can contain duplicated properties. Debug/breakpoint here while running C# generator (Dog and Cat models) m.readWriteVars.add(cp); } } diff --git a/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/CSharpClientCodegen.java b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/CSharpClientCodegen.java index a605fe36a94..294a095c260 100644 --- a/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/CSharpClientCodegen.java +++ b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/CSharpClientCodegen.java @@ -1,39 +1,23 @@ package io.swagger.codegen.languages; import com.google.common.collect.ImmutableMap; - -import com.sun.org.apache.bcel.internal.classfile.Code; - -import io.swagger.codegen.CodegenConstants; -import io.swagger.codegen.CodegenType; -import io.swagger.codegen.CodegenModel; -import io.swagger.codegen.CodegenParameter; -import io.swagger.codegen.SupportingFile; -import io.swagger.codegen.CodegenProperty; -import io.swagger.codegen.CodegenOperation; -import io.swagger.codegen.CliOption; +import io.swagger.codegen.*; import io.swagger.models.Model; - -import java.io.File; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.HashMap; -import java.util.Iterator; - import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.io.File; +import java.util.*; + import static org.apache.commons.lang3.StringUtils.isEmpty; public class CSharpClientCodegen extends AbstractCSharpCodegen { - @SuppressWarnings({"unused", "hiding"}) + @SuppressWarnings({"hiding"}) private static final Logger LOGGER = LoggerFactory.getLogger(CSharpClientCodegen.class); private static final String NET45 = "v4.5"; private static final String NET35 = "v3.5"; private static final String NETSTANDARD = "v5.0"; private static final String UWP = "uwp"; - private static final String DATA_TYPE_WITH_ENUM_EXTENSION = "plainDatatypeWithEnum"; protected String packageGuid = "{" + java.util.UUID.randomUUID().toString().toUpperCase() + "}"; protected String clientPackage = "IO.Swagger.Client"; @@ -55,6 +39,7 @@ public class CSharpClientCodegen extends AbstractCSharpCodegen { public CSharpClientCodegen() { super(); + supportsInheritance = true; modelTemplateFiles.put("model.mustache", ".cs"); apiTemplateFiles.put("api.mustache", ".cs"); @@ -181,16 +166,16 @@ public class CSharpClientCodegen extends AbstractCSharpCodegen { Boolean.valueOf(additionalProperties().get(CodegenConstants.HIDE_GENERATION_TIMESTAMP).toString())); } - if(isEmpty(apiPackage)) { + if (isEmpty(apiPackage)) { apiPackage = "Api"; } - if(isEmpty(modelPackage)) { + if (isEmpty(modelPackage)) { modelPackage = "Model"; } clientPackage = "Client"; Boolean excludeTests = false; - if(additionalProperties.containsKey(CodegenConstants.EXCLUDE_TESTS)) { + if (additionalProperties.containsKey(CodegenConstants.EXCLUDE_TESTS)) { excludeTests = Boolean.valueOf(additionalProperties.get(CodegenConstants.EXCLUDE_TESTS).toString()); } @@ -215,12 +200,12 @@ public class CSharpClientCodegen extends AbstractCSharpCodegen { if (NET35.equals(this.targetFramework)) { setTargetFrameworkNuget("net35"); setSupportsAsync(Boolean.FALSE); - if(additionalProperties.containsKey("supportsAsync")){ + if (additionalProperties.containsKey("supportsAsync")) { additionalProperties.remove("supportsAsync"); } additionalProperties.put("validatable", false); additionalProperties.put("net35", true); - } else if (NETSTANDARD.equals(this.targetFramework)){ + } else if (NETSTANDARD.equals(this.targetFramework)) { setTargetFrameworkNuget("netstandard1.3"); setSupportsAsync(Boolean.TRUE); setSupportsUWP(Boolean.FALSE); @@ -232,11 +217,11 @@ public class CSharpClientCodegen extends AbstractCSharpCodegen { //Tests not yet implemented for .NET Standard codegen //Todo implement it excludeTests = true; - if(additionalProperties.containsKey(CodegenConstants.EXCLUDE_TESTS)){ + if (additionalProperties.containsKey(CodegenConstants.EXCLUDE_TESTS)) { additionalProperties.remove(CodegenConstants.EXCLUDE_TESTS); } additionalProperties.put(CodegenConstants.EXCLUDE_TESTS, excludeTests); - } else if (UWP.equals(this.targetFramework)){ + } else if (UWP.equals(this.targetFramework)) { setTargetFrameworkNuget("uwp"); setSupportsAsync(Boolean.TRUE); setSupportsUWP(Boolean.TRUE); @@ -249,18 +234,18 @@ public class CSharpClientCodegen extends AbstractCSharpCodegen { additionalProperties.put("supportsAsync", this.supportsAsync); } - if(additionalProperties.containsKey(CodegenConstants.GENERATE_PROPERTY_CHANGED)) { - if(NET35.equals(targetFramework)) { + if (additionalProperties.containsKey(CodegenConstants.GENERATE_PROPERTY_CHANGED)) { + if (NET35.equals(targetFramework)) { LOGGER.warn(CodegenConstants.GENERATE_PROPERTY_CHANGED + " is only supported by generated code for .NET 4+."); - } else if(NETSTANDARD.equals(targetFramework)) { + } else if (NETSTANDARD.equals(targetFramework)) { LOGGER.warn(CodegenConstants.GENERATE_PROPERTY_CHANGED + " is not supported in .NET Standard generated code."); - } else if(Boolean.TRUE.equals(netCoreProjectFileFlag)) { + } else if (Boolean.TRUE.equals(netCoreProjectFileFlag)) { LOGGER.warn(CodegenConstants.GENERATE_PROPERTY_CHANGED + " is not supported in .NET Core csproj project format."); } else { setGeneratePropertyChanged(Boolean.valueOf(additionalProperties.get(CodegenConstants.GENERATE_PROPERTY_CHANGED).toString())); } - if(Boolean.FALSE.equals(this.generatePropertyChanged)) { + if (Boolean.FALSE.equals(this.generatePropertyChanged)) { additionalProperties.remove(CodegenConstants.GENERATE_PROPERTY_CHANGED); } } @@ -322,8 +307,10 @@ public class CSharpClientCodegen extends AbstractCSharpCodegen { clientPackageDir, "ExceptionFactory.cs")); supportingFiles.add(new SupportingFile("SwaggerDateConverter.mustache", clientPackageDir, "SwaggerDateConverter.cs")); + supportingFiles.add(new SupportingFile("JsonSubTypes.mustache", + clientPackageDir, "JsonSubTypes.cs")); - if(Boolean.FALSE.equals(this.netStandard) && Boolean.FALSE.equals(this.netCoreProjectFileFlag)) { + if (Boolean.FALSE.equals(this.netStandard) && Boolean.FALSE.equals(this.netCoreProjectFileFlag)) { supportingFiles.add(new SupportingFile("compile.mustache", "", "build.bat")); supportingFiles.add(new SupportingFile("compile-mono.sh.mustache", "", "build.sh")); @@ -331,7 +318,7 @@ public class CSharpClientCodegen extends AbstractCSharpCodegen { supportingFiles.add(new SupportingFile("packages.config.mustache", packageFolder + File.separator, "packages.config")); // .travis.yml for travis-ci.org CI supportingFiles.add(new SupportingFile("travis.mustache", "", ".travis.yml")); - } else if(Boolean.FALSE.equals(this.netCoreProjectFileFlag)) { + } else if (Boolean.FALSE.equals(this.netCoreProjectFileFlag)) { supportingFiles.add(new SupportingFile("project.json.mustache", packageFolder + File.separator, "project.json")); } @@ -341,7 +328,7 @@ public class CSharpClientCodegen extends AbstractCSharpCodegen { clientPackageDir, "GlobalConfiguration.cs")); // Only write out test related files if excludeTests is unset or explicitly set to false (see start of this method) - if(Boolean.FALSE.equals(excludeTests)) { + if (Boolean.FALSE.equals(excludeTests)) { // shell script to run the nunit test supportingFiles.add(new SupportingFile("mono_nunit_test.mustache", "", "mono_nunit_test.sh")); @@ -353,7 +340,7 @@ public class CSharpClientCodegen extends AbstractCSharpCodegen { } } - if(Boolean.TRUE.equals(generatePropertyChanged)) { + if (Boolean.TRUE.equals(generatePropertyChanged)) { supportingFiles.add(new SupportingFile("FodyWeavers.xml", packageFolder, "FodyWeavers.xml")); } @@ -369,19 +356,19 @@ public class CSharpClientCodegen extends AbstractCSharpCodegen { } if (optionalProjectFileFlag) { supportingFiles.add(new SupportingFile("Solution.mustache", "", packageName + ".sln")); - - if(Boolean.TRUE.equals(this.netCoreProjectFileFlag)) { + + if (Boolean.TRUE.equals(this.netCoreProjectFileFlag)) { supportingFiles.add(new SupportingFile("netcore_project.mustache", packageFolder, packageName + ".csproj")); } else { supportingFiles.add(new SupportingFile("Project.mustache", packageFolder, packageName + ".csproj")); - if(Boolean.FALSE.equals(this.netStandard)) { + if (Boolean.FALSE.equals(this.netStandard)) { supportingFiles.add(new SupportingFile("nuspec.mustache", packageFolder, packageName + ".nuspec")); } } - if(Boolean.FALSE.equals(excludeTests)) { + if (Boolean.FALSE.equals(excludeTests)) { // NOTE: This exists here rather than previous excludeTests block because the test project is considered an optional project file. - if(Boolean.TRUE.equals(this.netCoreProjectFileFlag)) { + if (Boolean.TRUE.equals(this.netCoreProjectFileFlag)) { supportingFiles.add(new SupportingFile("netcore_testproject.mustache", testPackageFolder, testPackageName + ".csproj")); } else { supportingFiles.add(new SupportingFile("TestProject.mustache", testPackageFolder, testPackageName + ".csproj")); @@ -457,10 +444,54 @@ public class CSharpClientCodegen extends AbstractCSharpCodegen { @Override public CodegenModel fromModel(String name, Model model, Map allDefinitions) { CodegenModel codegenModel = super.fromModel(name, model, allDefinitions); - if (allDefinitions != null && codegenModel != null && codegenModel.parent != null && codegenModel.hasEnums) { + if (allDefinitions != null && codegenModel != null && codegenModel.parent != null) { final Model parentModel = allDefinitions.get(toModelName(codegenModel.parent)); - final CodegenModel parentCodegenModel = super.fromModel(codegenModel.parent, parentModel); - codegenModel = this.reconcileInlineEnums(codegenModel, parentCodegenModel); + if (parentModel != null) { + final CodegenModel parentCodegenModel = super.fromModel(codegenModel.parent, parentModel); + if (codegenModel.hasEnums) { + codegenModel = this.reconcileInlineEnums(codegenModel, parentCodegenModel); + } + + Map propertyHash = new HashMap<>(codegenModel.vars.size()); + for (final CodegenProperty property : codegenModel.vars) { + propertyHash.put(property.name, property); + } + + for (final CodegenProperty property : codegenModel.readWriteVars) { + if (property.defaultValue == null && property.baseName.equals(parentCodegenModel.discriminator)) { + property.defaultValue = "\"" + name + "\""; + } + } + + CodegenProperty last = null; + for (final CodegenProperty property : parentCodegenModel.vars) { + // helper list of parentVars simplifies templating + if (!propertyHash.containsKey(property.name)) { + final CodegenProperty parentVar = property.clone(); + parentVar.isInherited = true; + parentVar.hasMore = true; + last = parentVar; + LOGGER.info("adding parent variable {}", property.name); + codegenModel.parentVars.add(parentVar); + } + } + + if (last != null) { + last.hasMore = false; + } + } + } + + // Cleanup possible duplicates. Currently, readWriteVars can contain the same property twice. May or may not be isolated to C#. + if (codegenModel != null && codegenModel.readWriteVars != null && codegenModel.readWriteVars.size() > 1) { + int length = codegenModel.readWriteVars.size() - 1; + for (int i = length; i > (length / 2); i--) { + final CodegenProperty codegenProperty = codegenModel.readWriteVars.get(i); + // If the property at current index is found earlier in the list, remove this last instance. + if (codegenModel.readWriteVars.indexOf(codegenProperty) < i) { + codegenModel.readWriteVars.remove(i); + } + } } return codegenModel; @@ -500,13 +531,13 @@ public class CSharpClientCodegen extends AbstractCSharpCodegen { * See https://github.com/swagger-api/swagger-codegen/pull/2794 for Python's initial implementation from which this is copied. */ public void postProcessPattern(String pattern, Map vendorExtensions) { - if(pattern != null) { + if (pattern != null) { int i = pattern.lastIndexOf('/'); //Must follow Perl /pattern/modifiers convention - if(pattern.charAt(0) != '/' || i < 2) { + if (pattern.charAt(0) != '/' || i < 2) { throw new IllegalArgumentException("Pattern must follow the Perl " - + "/pattern/modifiers convention. "+pattern+" is not valid."); + + "/pattern/modifiers convention. " + pattern + " is not valid."); } String regex = pattern.substring(1, i).replace("'", "\'"); @@ -515,8 +546,8 @@ public class CSharpClientCodegen extends AbstractCSharpCodegen { // perl requires an explicit modifier to be culture specific and .NET is the reverse. modifiers.add("CultureInvariant"); - for(char c : pattern.substring(i).toCharArray()) { - if(regexModifiers.containsKey(c)) { + for (char c : pattern.substring(i).toCharArray()) { + if (regexModifiers.containsKey(c)) { String modifier = regexModifiers.get(c); modifiers.add(modifier); } else if (c == 'l') { @@ -530,7 +561,7 @@ public class CSharpClientCodegen extends AbstractCSharpCodegen { } public void setTargetFramework(String dotnetFramework) { - if(!frameworks.containsKey(dotnetFramework)){ + if (!frameworks.containsKey(dotnetFramework)) { LOGGER.warn("Invalid .NET framework version, defaulting to " + this.targetFramework); } else { this.targetFramework = dotnetFramework; @@ -572,10 +603,10 @@ public class CSharpClientCodegen extends AbstractCSharpCodegen { } } - if(removedChildEnum) { + if (removedChildEnum) { // If we removed an entry from this model's vars, we need to ensure hasMore is updated int count = 0, numVars = codegenProperties.size(); - for(CodegenProperty codegenProperty : codegenProperties) { + for (CodegenProperty codegenProperty : codegenProperties) { count += 1; codegenProperty.hasMore = count < numVars; } @@ -589,7 +620,7 @@ public class CSharpClientCodegen extends AbstractCSharpCodegen { @Override public String toEnumValue(String value, String datatype) { if ("int?".equalsIgnoreCase(datatype) || "long?".equalsIgnoreCase(datatype) || - "double?".equalsIgnoreCase(datatype) || "float?".equalsIgnoreCase(datatype)) { + "double?".equalsIgnoreCase(datatype) || "float?".equalsIgnoreCase(datatype)) { return value; } else if ("float?".equalsIgnoreCase(datatype)) { // for float in C#, append "f". e.g. 3.14 => 3.14f @@ -611,8 +642,8 @@ public class CSharpClientCodegen extends AbstractCSharpCodegen { } // number - if ("int?".equals(datatype) || "long?".equals(datatype) || - "double?".equals(datatype) || "float?".equals(datatype)) { + if ("int?".equals(datatype) || "long?".equals(datatype) || + "double?".equals(datatype) || "float?".equals(datatype)) { String varName = "NUMBER_" + value; varName = varName.replaceAll("-", "MINUS_"); varName = varName.replaceAll("\\+", "PLUS_"); @@ -678,19 +709,19 @@ public class CSharpClientCodegen extends AbstractCSharpCodegen { this.targetFrameworkNuget = targetFrameworkNuget; } - public void setSupportsAsync(Boolean supportsAsync){ + public void setSupportsAsync(Boolean supportsAsync) { this.supportsAsync = supportsAsync; } - public void setSupportsUWP(Boolean supportsUWP){ + public void setSupportsUWP(Boolean supportsUWP) { this.supportsUWP = supportsUWP; } - public void setNetStandard(Boolean netStandard){ + public void setNetStandard(Boolean netStandard) { this.netStandard = netStandard; } - public void setGeneratePropertyChanged(final Boolean generatePropertyChanged){ + public void setGeneratePropertyChanged(final Boolean generatePropertyChanged) { this.generatePropertyChanged = generatePropertyChanged; } diff --git a/modules/swagger-codegen/src/main/resources/csharp/JsonSubTypes.mustache b/modules/swagger-codegen/src/main/resources/csharp/JsonSubTypes.mustache new file mode 100644 index 00000000000..3a6da091b78 --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/csharp/JsonSubTypes.mustache @@ -0,0 +1,272 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; + +namespace JsonSubTypes +{ + // Copied from project https://github.com/manuc66/JsonSubTypes + // https://raw.githubusercontent.com/manuc66/JsonSubTypes/07403192ea3f4959f6d42f5966ac56ceb0d6095b/JsonSubTypes/JsonSubtypes.cs + + public class JsonSubtypes : JsonConverter + { + [AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface, AllowMultiple = true)] + public class KnownSubTypeAttribute : Attribute + { + public Type SubType { get; private set; } + public object AssociatedValue { get; private set; } + + public KnownSubTypeAttribute(Type subType, object associatedValue) + { + SubType = subType; + AssociatedValue = associatedValue; + } + } + [AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface, AllowMultiple = true)] + public class KnownSubTypeWithPropertyAttribute : Attribute + { + public Type SubType { get; private set; } + public string PropertyName { get; private set; } + + public KnownSubTypeWithPropertyAttribute(Type subType, string propertyName) + { + SubType = subType; + PropertyName = propertyName; + } + } + + private readonly string _typeMappingPropertyName; + + private bool _isInsideRead; + private JsonReader _reader; + + public override bool CanRead + { + get + { + if (!_isInsideRead) + return true; + + return !string.IsNullOrEmpty(_reader.Path); + } + } + + public sealed override bool CanWrite + { + get { return false; } + } + + public JsonSubtypes() + { + } + + public JsonSubtypes(string typeMappingPropertyName) + { + _typeMappingPropertyName = typeMappingPropertyName; + } + + public override bool CanConvert(Type objectType) + { + return _typeMappingPropertyName != null; + } + + public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) + { + throw new NotImplementedException(); + } + + public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) + { + if (reader.TokenType == JsonToken.Comment) + reader.Read(); + + switch (reader.TokenType) + { + case JsonToken.Null: + return null; + case JsonToken.StartArray: + return ReadArray(reader, objectType, serializer); + case JsonToken.StartObject: + return ReadObject(reader, objectType, serializer); + default: + throw new Exception("Array: Unrecognized token: " + reader.TokenType); + } + } + + private IList ReadArray(JsonReader reader, Type targetType, JsonSerializer serializer) + { + var elementType = GetElementType(targetType); + + var list = CreateCompatibleList(targetType, elementType); + + while (reader.TokenType != JsonToken.EndArray && reader.Read()) + { + switch (reader.TokenType) + { + case JsonToken.Null: + list.Add(reader.Value); + break; + case JsonToken.Comment: + break; + case JsonToken.StartObject: + list.Add(ReadObject(reader, elementType, serializer)); + break; + case JsonToken.EndArray: + break; + default: + throw new Exception("Array: Unrecognized token: " + reader.TokenType); + } + } + if (targetType.IsArray) + { + var array = Array.CreateInstance(targetType.GetElementType(), list.Count); + list.CopyTo(array, 0); + list = array; + } + return list; + } + + private static IList CreateCompatibleList(Type targetContainerType, Type elementType) + { + IList list; + if (targetContainerType.IsArray || targetContainerType.GetTypeInfo().IsAbstract) + { + list = (IList)Activator.CreateInstance(typeof(List<>).MakeGenericType(elementType)); + } + else + { + list = (IList)Activator.CreateInstance(targetContainerType); + } + return list; + } + + private static Type GetElementType(Type arrayOrGenericContainer) + { + Type elementType; + if (arrayOrGenericContainer.IsArray) + { + elementType = arrayOrGenericContainer.GetElementType(); + } + else + { + elementType = arrayOrGenericContainer.GenericTypeArguments[0]; + } + return elementType; + } + + private object ReadObject(JsonReader reader, Type objectType, JsonSerializer serializer) + { + var jObject = JObject.Load(reader); + + var targetType = GetType(jObject, objectType) ?? objectType; + + return _ReadJson(CreateAnotherReader(jObject, reader), targetType, null, serializer); + } + + private static JsonReader CreateAnotherReader(JObject jObject, JsonReader reader) + { + var jObjectReader = jObject.CreateReader(); + jObjectReader.Culture = reader.Culture; + jObjectReader.CloseInput = reader.CloseInput; + jObjectReader.SupportMultipleContent = reader.SupportMultipleContent; + jObjectReader.DateTimeZoneHandling = reader.DateTimeZoneHandling; + jObjectReader.FloatParseHandling = reader.FloatParseHandling; + jObjectReader.DateFormatString = reader.DateFormatString; + jObjectReader.DateParseHandling = reader.DateParseHandling; + return jObjectReader; + } + + public Type GetType(JObject jObject, Type parentType) + { + if (_typeMappingPropertyName == null) + { + return GetTypeByPropertyPresence(jObject, parentType); + } + return GetTypeFromDiscriminatorValue(jObject, parentType); + } + + private static Type GetTypeByPropertyPresence(JObject jObject, Type parentType) + { + foreach (var type in parentType.GetTypeInfo().GetCustomAttributes()) + { + JToken ignore; + if (jObject.TryGetValue(type.PropertyName, out ignore)) + { + return type.SubType; + } + } + return null; + } + + private Type GetTypeFromDiscriminatorValue(JObject jObject, Type parentType) + { + JToken jToken; + if (!jObject.TryGetValue(_typeMappingPropertyName, out jToken)) return null; + + var discriminatorValue = jToken.ToObject(); + if (discriminatorValue == null) return null; + + var typeMapping = GetSubTypeMapping(parentType); + if (typeMapping.Any()) + { + return GetTypeFromMapping(typeMapping, discriminatorValue); + } + return GetTypeByName(discriminatorValue as string, parentType); + } + + private static Type GetTypeByName(string typeName, Type parentType) + { + if (typeName == null) + return null; + + var insideAssembly = parentType.GetTypeInfo().Assembly; + + var typeByName = insideAssembly.GetType(typeName); + if (typeByName == null) + { + var searchLocation = parentType.FullName.Substring(0, parentType.FullName.Length - parentType.Name.Length); + typeByName = insideAssembly.GetType(searchLocation + typeName, false, true); + } + return typeByName; + } + + private static Type GetTypeFromMapping(IReadOnlyDictionary typeMapping, object discriminatorValue) + { + var targetlookupValueType = typeMapping.First().Key.GetType(); + var lookupValue = ConvertJsonValueToType(discriminatorValue, targetlookupValueType); + + Type targetType; + return typeMapping.TryGetValue(lookupValue, out targetType) ? targetType : null; + } + + private static Dictionary GetSubTypeMapping(Type type) + { + return type.GetTypeInfo().GetCustomAttributes().ToDictionary(x => x.AssociatedValue, x => x.SubType); + } + + private static object ConvertJsonValueToType(object objectType, Type targetlookupValueType) + { + if (targetlookupValueType.GetTypeInfo().IsEnum) + return Enum.ToObject(targetlookupValueType, objectType); + + return Convert.ChangeType(objectType, targetlookupValueType); + } + + protected object _ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) + { + _reader = reader; + _isInsideRead = true; + try + { + return serializer.Deserialize(reader, objectType); + } + finally + { + _isInsideRead = false; + } + } + } +} diff --git a/modules/swagger-codegen/src/main/resources/csharp/Solution.mustache b/modules/swagger-codegen/src/main/resources/csharp/Solution.mustache index 183dbe21c8d..112cc3dc405 100644 --- a/modules/swagger-codegen/src/main/resources/csharp/Solution.mustache +++ b/modules/swagger-codegen/src/main/resources/csharp/Solution.mustache @@ -7,21 +7,21 @@ EndProject {{^excludeTests}}Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "{{testPackageName}}", "src\{{testPackageName}}\{{testPackageName}}.csproj", "{19F1DEBC-DE5E-4517-8062-F000CD499087}" EndProject {{/excludeTests}}Global -GlobalSection(SolutionConfigurationPlatforms) = preSolution -Debug|Any CPU = Debug|Any CPU -Release|Any CPU = Release|Any CPU -EndGlobalSection -GlobalSection(ProjectConfigurationPlatforms) = postSolution -{{packageGuid}}.Debug|Any CPU.ActiveCfg = Debug|Any CPU -{{packageGuid}}.Debug|Any CPU.Build.0 = Debug|Any CPU -{{packageGuid}}.Release|Any CPU.ActiveCfg = Release|Any CPU -{{packageGuid}}.Release|Any CPU.Build.0 = Release|Any CPU -{19F1DEBC-DE5E-4517-8062-F000CD499087}.Debug|Any CPU.ActiveCfg = Debug|Any CPU -{19F1DEBC-DE5E-4517-8062-F000CD499087}.Debug|Any CPU.Build.0 = Debug|Any CPU -{19F1DEBC-DE5E-4517-8062-F000CD499087}.Release|Any CPU.ActiveCfg = Release|Any CPU -{19F1DEBC-DE5E-4517-8062-F000CD499087}.Release|Any CPU.Build.0 = Release|Any CPU -EndGlobalSection -GlobalSection(SolutionProperties) = preSolution -HideSolutionNode = FALSE -EndGlobalSection + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {{packageGuid}}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {{packageGuid}}.Debug|Any CPU.Build.0 = Debug|Any CPU + {{packageGuid}}.Release|Any CPU.ActiveCfg = Release|Any CPU + {{packageGuid}}.Release|Any CPU.Build.0 = Release|Any CPU + {19F1DEBC-DE5E-4517-8062-F000CD499087}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {19F1DEBC-DE5E-4517-8062-F000CD499087}.Debug|Any CPU.Build.0 = Debug|Any CPU + {19F1DEBC-DE5E-4517-8062-F000CD499087}.Release|Any CPU.ActiveCfg = Release|Any CPU + {19F1DEBC-DE5E-4517-8062-F000CD499087}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection EndGlobal \ No newline at end of file diff --git a/modules/swagger-codegen/src/main/resources/csharp/model.mustache b/modules/swagger-codegen/src/main/resources/csharp/model.mustache index ac36ce6763d..9f49989303c 100644 --- a/modules/swagger-codegen/src/main/resources/csharp/model.mustache +++ b/modules/swagger-codegen/src/main/resources/csharp/model.mustache @@ -12,6 +12,13 @@ using System.Collections.ObjectModel; using System.Runtime.Serialization; using Newtonsoft.Json; using Newtonsoft.Json.Converters; +{{#models}} +{{#model}} +{{#discriminator}} +using JsonSubTypes; +{{/discriminator}} +{{/model}} +{{/models}} {{^netStandard}} {{#generatePropertyChanged}} using PropertyChanged; diff --git a/modules/swagger-codegen/src/main/resources/csharp/modelGeneric.mustache b/modules/swagger-codegen/src/main/resources/csharp/modelGeneric.mustache index c206b06365a..990818fd328 100644 --- a/modules/swagger-codegen/src/main/resources/csharp/modelGeneric.mustache +++ b/modules/swagger-codegen/src/main/resources/csharp/modelGeneric.mustache @@ -2,6 +2,10 @@ /// {{#description}}{{.}}{{/description}}{{^description}}{{classname}}{{/description}} /// [DataContract] + {{#discriminator}} + [JsonConverter(typeof(JsonSubtypes), "{{discriminator}}")]{{#children}} + [JsonSubtypes.KnownSubType(typeof({{classname}}), "{{^vendorExtensions.x-discriminator-value}}{{name}}{{/vendorExtensions.x-discriminator-value}}{{#vendorExtensions.x-discriminator-value}}{{{vendorExtensions.x-discriminator-value}}}{{/vendorExtensions.x-discriminator-value}}")]{{/children}} + {{/discriminator}} {{#generatePropertyChanged}} [ImplementPropertyChanged] {{/generatePropertyChanged}} @@ -49,9 +53,10 @@ {{#hasOnlyReadOnly}} [JsonConstructorAttribute] {{/hasOnlyReadOnly}} - public {{classname}}({{#readWriteVars}}{{{datatypeWithEnum}}}{{#isEnum}}{{^isContainer}}?{{/isContainer}}{{/isEnum}} {{name}} = {{#defaultValue}}{{{defaultValue}}}{{/defaultValue}}{{^defaultValue}}default({{{datatypeWithEnum}}}{{#isEnum}}{{^isContainer}}?{{/isContainer}}{{/isEnum}}){{/defaultValue}}{{^-last}}, {{/-last}}{{/readWriteVars}}) + public {{classname}}({{#readWriteVars}}{{{datatypeWithEnum}}}{{#isEnum}}{{^isContainer}}?{{/isContainer}}{{/isEnum}} {{name}} = {{#defaultValue}}{{{defaultValue}}}{{/defaultValue}}{{^defaultValue}}default({{{datatypeWithEnum}}}{{#isEnum}}{{^isContainer}}?{{/isContainer}}{{/isEnum}}){{/defaultValue}}{{^-last}}, {{/-last}}{{/readWriteVars}}){{#parent}} : base({{#parentVars}}{{name}}{{#hasMore}}, {{/hasMore}}{{/parentVars}}){{/parent}} { {{#vars}} + {{^isInherited}} {{^isReadOnly}} {{#required}} // to ensure "{{name}}" is required (not null) @@ -65,8 +70,10 @@ } {{/required}} {{/isReadOnly}} + {{/isInherited}} {{/vars}} {{#vars}} + {{^isInherited}} {{^isReadOnly}} {{^required}} {{#defaultValue}}// use default value if no "{{name}}" provided @@ -84,10 +91,12 @@ this.{{name}} = {{name}}; {{/defaultValue}} {{/required}} {{/isReadOnly}} + {{/isInherited}} {{/vars}} } {{#vars}} + {{^isInherited}} {{^isEnum}} /// /// {{^description}}Gets or Sets {{{name}}}{{/description}}{{#description}}{{description}}{{/description}} @@ -97,6 +106,7 @@ this.{{name}} = {{name}}; [JsonConverter(typeof(SwaggerDateConverter))]{{/isDate}} public {{{datatype}}} {{name}} { get; {{#isReadOnly}}private {{/isReadOnly}}set; } {{/isEnum}} + {{/isInherited}} {{/vars}} /// @@ -107,6 +117,9 @@ this.{{name}} = {{name}}; { var sb = new StringBuilder(); sb.Append("class {{classname}} {\n"); + {{#parent}} + sb.Append(" ").Append(base.ToString().Replace("\n", "\n ")).Append("\n"); + {{/parent}} {{#vars}} sb.Append(" {{name}}: ").Append({{name}}).Append("\n"); {{/vars}} @@ -118,7 +131,7 @@ this.{{name}} = {{name}}; /// Returns the JSON string presentation of the object /// /// JSON string presentation of the object - public {{#parent}} new {{/parent}}string ToJson() + public {{#parent}}{{^isArrayModel}}override {{/isArrayModel}}{{/parent}}{{^parent}}{{#discriminator}}virtual {{/discriminator}}{{/parent}}string ToJson() { return JsonConvert.SerializeObject(this, Formatting.Indented); } @@ -143,7 +156,7 @@ this.{{name}} = {{name}}; if (input == null) return false; - return {{#vars}}{{#isNotContainer}} + return {{#vars}}{{#parent}}base.Equals(input) && {{/parent}}{{#isNotContainer}} ( this.{{name}} == input.{{name}} || (this.{{name}} != null && @@ -151,9 +164,9 @@ this.{{name}} = {{name}}; ){{#hasMore}} && {{/hasMore}}{{/isNotContainer}}{{^isNotContainer}} ( this.{{name}} == input.{{name}} || - (this.{{name}} != null && - this.{{name}}.SequenceEqual(input.{{name}})) - ){{#hasMore}} && {{/hasMore}}{{/isNotContainer}}{{/vars}}{{^vars}}false{{/vars}}; + this.{{name}} != null && + this.{{name}}.SequenceEqual(input.{{name}}) + ){{#hasMore}} && {{/hasMore}}{{/isNotContainer}}{{/vars}}{{^vars}}{{#parent}}base.Equals(input){{/parent}}{{^parent}}false{{/parent}}{{/vars}}; } /// @@ -164,7 +177,12 @@ this.{{name}} = {{name}}; { unchecked // Overflow is fine, just wrap { + {{#parent}} + int hashCode = base.GetHashCode(); + {{/parent}} + {{^parent}} int hashCode = 41; + {{/parent}} {{#vars}} if (this.{{name}} != null) hashCode = hashCode * 59 + this.{{name}}.GetHashCode(); @@ -197,6 +215,7 @@ this.{{name}} = {{name}}; {{/generatePropertyChanged}} {{#validatable}} +{{#discriminator}} /// /// To validate all properties of the instance /// @@ -204,6 +223,31 @@ this.{{name}} = {{name}}; /// Validation Result IEnumerable IValidatableObject.Validate(ValidationContext validationContext) { + return this.BaseValidate(validationContext); + } + + /// + /// To validate all properties of the instance + /// + /// Validation context + /// Validation Result + protected IEnumerable BaseValidate(ValidationContext validationContext) + { +{{/discriminator}} +{{^discriminator}} + /// + /// To validate all properties of the instance + /// + /// Validation context + /// Validation Result + IEnumerable IValidatableObject.Validate(ValidationContext validationContext) + { +{{/discriminator}} + {{#parent}} + {{^isArrayModel}} + foreach(var x in BaseValidate(validationContext)) yield return x; + {{/isArrayModel}} + {{/parent}} {{#vars}} {{#hasValidation}} {{#maxLength}} diff --git a/modules/swagger-codegen/src/main/resources/csharp/model_doc.mustache b/modules/swagger-codegen/src/main/resources/csharp/model_doc.mustache index 112d4725495..0b62dadc6da 100644 --- a/modules/swagger-codegen/src/main/resources/csharp/model_doc.mustache +++ b/modules/swagger-codegen/src/main/resources/csharp/model_doc.mustache @@ -5,6 +5,11 @@ Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- +{{#parent}} +{{#parentVars}} +**{{name}}** | {{#isPrimitiveType}}**{{datatype}}**{{/isPrimitiveType}}{{^isPrimitiveType}}[**{{datatype}}**]({{complexType}}.md){{/isPrimitiveType}} | {{description}} | {{^required}}[optional] {{/required}}{{#readOnly}}[readonly] {{/readOnly}}{{#defaultValue}}[default to {{{.}}}]{{/defaultValue}} +{{/parentVars}} +{{/parent}} {{#vars}}**{{name}}** | {{#isPrimitiveType}}**{{datatype}}**{{/isPrimitiveType}}{{^isPrimitiveType}}[**{{datatype}}**]({{complexType}}.md){{/isPrimitiveType}} | {{description}} | {{^required}}[optional] {{/required}}{{#readOnly}}[readonly] {{/readOnly}}{{#defaultValue}}[default to {{{.}}}]{{/defaultValue}} {{/vars}} diff --git a/modules/swagger-codegen/src/main/resources/csharp/model_test.mustache b/modules/swagger-codegen/src/main/resources/csharp/model_test.mustache index f059706af14..3a433b5f301 100644 --- a/modules/swagger-codegen/src/main/resources/csharp/model_test.mustache +++ b/modules/swagger-codegen/src/main/resources/csharp/model_test.mustache @@ -10,6 +10,7 @@ using {{packageName}}.{{apiPackage}}; using {{packageName}}.{{modelPackage}}; using {{packageName}}.Client; using System.Reflection; +using Newtonsoft.Json; {{#models}} {{#model}} @@ -57,6 +58,20 @@ namespace {{packageName}}.Test //Assert.IsInstanceOfType<{{classname}}> (instance, "variable 'instance' is a {{classname}}"); } + {{#discriminator}} + {{#children}} + /// + /// Test deserialize a {{classname}} from type {{parent}} + /// + [Test] + public void {{classname}}DeserializeFrom{{parent}}Test() + { + // TODO uncomment below to test deserialize a {{classname}} from type {{parent}} + //Assert.IsInstanceOf<{{parent}}>(JsonConvert.DeserializeObject<{{parent}}>(new {{classname}}().ToJson())); + } + {{/children}} + {{/discriminator}} + {{#vars}} /// /// Test the property '{{name}}' diff --git a/samples/client/petstore-security-test/csharp/SwaggerClient/.swagger-codegen/VERSION b/samples/client/petstore-security-test/csharp/SwaggerClient/.swagger-codegen/VERSION index 7fea99011a6..f9f7450d135 100644 --- a/samples/client/petstore-security-test/csharp/SwaggerClient/.swagger-codegen/VERSION +++ b/samples/client/petstore-security-test/csharp/SwaggerClient/.swagger-codegen/VERSION @@ -1 +1 @@ -2.2.3-SNAPSHOT \ No newline at end of file +2.3.0-SNAPSHOT \ No newline at end of file diff --git a/samples/client/petstore-security-test/csharp/SwaggerClient/IO.Swagger.sln b/samples/client/petstore-security-test/csharp/SwaggerClient/IO.Swagger.sln index 8dcf7f24348..564be8b65c2 100644 --- a/samples/client/petstore-security-test/csharp/SwaggerClient/IO.Swagger.sln +++ b/samples/client/petstore-security-test/csharp/SwaggerClient/IO.Swagger.sln @@ -7,21 +7,21 @@ EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "IO.Swagger.Test", "src\IO.Swagger.Test\IO.Swagger.Test.csproj", "{19F1DEBC-DE5E-4517-8062-F000CD499087}" EndProject Global -GlobalSection(SolutionConfigurationPlatforms) = preSolution -Debug|Any CPU = Debug|Any CPU -Release|Any CPU = Release|Any CPU -EndGlobalSection -GlobalSection(ProjectConfigurationPlatforms) = postSolution -{8CE139DF-64BC-4591-85F8-8506C2B67514}.Debug|Any CPU.ActiveCfg = Debug|Any CPU -{8CE139DF-64BC-4591-85F8-8506C2B67514}.Debug|Any CPU.Build.0 = Debug|Any CPU -{8CE139DF-64BC-4591-85F8-8506C2B67514}.Release|Any CPU.ActiveCfg = Release|Any CPU -{8CE139DF-64BC-4591-85F8-8506C2B67514}.Release|Any CPU.Build.0 = Release|Any CPU -{19F1DEBC-DE5E-4517-8062-F000CD499087}.Debug|Any CPU.ActiveCfg = Debug|Any CPU -{19F1DEBC-DE5E-4517-8062-F000CD499087}.Debug|Any CPU.Build.0 = Debug|Any CPU -{19F1DEBC-DE5E-4517-8062-F000CD499087}.Release|Any CPU.ActiveCfg = Release|Any CPU -{19F1DEBC-DE5E-4517-8062-F000CD499087}.Release|Any CPU.Build.0 = Release|Any CPU -EndGlobalSection -GlobalSection(SolutionProperties) = preSolution -HideSolutionNode = FALSE -EndGlobalSection + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {8CE139DF-64BC-4591-85F8-8506C2B67514}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8CE139DF-64BC-4591-85F8-8506C2B67514}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8CE139DF-64BC-4591-85F8-8506C2B67514}.Release|Any CPU.ActiveCfg = Release|Any CPU + {8CE139DF-64BC-4591-85F8-8506C2B67514}.Release|Any CPU.Build.0 = Release|Any CPU + {19F1DEBC-DE5E-4517-8062-F000CD499087}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {19F1DEBC-DE5E-4517-8062-F000CD499087}.Debug|Any CPU.Build.0 = Debug|Any CPU + {19F1DEBC-DE5E-4517-8062-F000CD499087}.Release|Any CPU.ActiveCfg = Release|Any CPU + {19F1DEBC-DE5E-4517-8062-F000CD499087}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection EndGlobal \ No newline at end of file diff --git a/samples/client/petstore-security-test/csharp/SwaggerClient/src/IO.Swagger/Api/FakeApi.cs b/samples/client/petstore-security-test/csharp/SwaggerClient/src/IO.Swagger/Api/FakeApi.cs index 63555667e9a..fa50c6bd07e 100644 --- a/samples/client/petstore-security-test/csharp/SwaggerClient/src/IO.Swagger/Api/FakeApi.cs +++ b/samples/client/petstore-security-test/csharp/SwaggerClient/src/IO.Swagger/Api/FakeApi.cs @@ -83,15 +83,9 @@ namespace IO.Swagger.Api /// public FakeApi(String basePath) { - this.Configuration = new Configuration(new ApiClient(basePath)); + this.Configuration = new Configuration { BasePath = basePath }; ExceptionFactory = IO.Swagger.Client.Configuration.DefaultExceptionFactory; - - // ensure API client has configuration ready - if (Configuration.ApiClient.Configuration == null) - { - this.Configuration.ApiClient.Configuration = this.Configuration; - } } /// @@ -108,12 +102,6 @@ namespace IO.Swagger.Api this.Configuration = configuration; ExceptionFactory = IO.Swagger.Client.Configuration.DefaultExceptionFactory; - - // ensure API client has configuration ready - if (Configuration.ApiClient.Configuration == null) - { - this.Configuration.ApiClient.Configuration = this.Configuration; - } } /// @@ -162,9 +150,9 @@ namespace IO.Swagger.Api /// /// Dictionary of HTTP header [Obsolete("DefaultHeader is deprecated, please use Configuration.DefaultHeader instead.")] - public Dictionary DefaultHeader() + public IDictionary DefaultHeader() { - return this.Configuration.DefaultHeader; + return new ReadOnlyDictionary(this.Configuration.DefaultHeader); } /// @@ -201,7 +189,7 @@ namespace IO.Swagger.Api var localVarPath = "/fake"; var localVarPathParams = new Dictionary(); - var localVarQueryParams = new Dictionary(); + var localVarQueryParams = new List>(); var localVarHeaderParams = new Dictionary(Configuration.DefaultHeader); var localVarFormParams = new Dictionary(); var localVarFileParams = new Dictionary(); @@ -267,7 +255,7 @@ namespace IO.Swagger.Api var localVarPath = "/fake"; var localVarPathParams = new Dictionary(); - var localVarQueryParams = new Dictionary(); + var localVarQueryParams = new List>(); var localVarHeaderParams = new Dictionary(Configuration.DefaultHeader); var localVarFormParams = new Dictionary(); var localVarFileParams = new Dictionary(); diff --git a/samples/client/petstore-security-test/csharp/SwaggerClient/src/IO.Swagger/Client/ApiClient.cs b/samples/client/petstore-security-test/csharp/SwaggerClient/src/IO.Swagger/Client/ApiClient.cs index 0763aa3ce27..f94789ba974 100644 --- a/samples/client/petstore-security-test/csharp/SwaggerClient/src/IO.Swagger/Client/ApiClient.cs +++ b/samples/client/petstore-security-test/csharp/SwaggerClient/src/IO.Swagger/Client/ApiClient.cs @@ -48,11 +48,11 @@ namespace IO.Swagger.Client /// /// Initializes a new instance of the class - /// with default configuration and base path (https://petstore.swagger.io *_/ ' \" =end - - \\r\\n \\n \\r/v2 *_/ ' \" =end - - \\r\\n \\n \\r). + /// with default configuration. /// public ApiClient() { - Configuration = Configuration.Default; + Configuration = IO.Swagger.Client.Configuration.Default; RestClient = new RestClient("https://petstore.swagger.io *_/ ' \" =end - - \\r\\n \\n \\r/v2 *_/ ' \" =end - - \\r\\n \\n \\r"); } @@ -61,14 +61,11 @@ namespace IO.Swagger.Client /// with default base path (https://petstore.swagger.io *_/ ' \" =end - - \\r\\n \\n \\r/v2 *_/ ' \" =end - - \\r\\n \\n \\r). /// /// An instance of Configuration. - public ApiClient(Configuration config = null) + public ApiClient(Configuration config) { - if (config == null) - Configuration = Configuration.Default; - else - Configuration = config; + Configuration = config ?? IO.Swagger.Client.Configuration.Default; - RestClient = new RestClient("https://petstore.swagger.io *_/ ' \" =end - - \\r\\n \\n \\r/v2 *_/ ' \" =end - - \\r\\n \\n \\r"); + RestClient = new RestClient(Configuration.BasePath); } /// @@ -82,7 +79,7 @@ namespace IO.Swagger.Client throw new ArgumentException("basePath cannot be empty"); RestClient = new RestClient(basePath); - Configuration = Configuration.Default; + Configuration = Client.Configuration.Default; } /// @@ -93,10 +90,15 @@ namespace IO.Swagger.Client public static ApiClient Default; /// - /// Gets or sets the Configuration. + /// Gets or sets an instance of the IReadableConfiguration. /// - /// An instance of the Configuration. - public Configuration Configuration { get; set; } + /// An instance of the IReadableConfiguration. + /// + /// helps us to avoid modifying possibly global + /// configuration values from within a given client. It does not gaurantee thread-safety + /// of the instance in any way. + /// + public IReadableConfiguration Configuration { get; set; } /// /// Gets or sets the RestClient. @@ -106,7 +108,7 @@ namespace IO.Swagger.Client // Creates and sets up a RestRequest prior to a call. private RestRequest PrepareRequest( - String path, RestSharp.Method method, Dictionary queryParams, Object postBody, + String path, RestSharp.Method method, List> queryParams, Object postBody, Dictionary headerParams, Dictionary formParams, Dictionary fileParams, Dictionary pathParams, String contentType) @@ -164,7 +166,7 @@ namespace IO.Swagger.Client /// Content Type of the request /// Object public Object CallApi( - String path, RestSharp.Method method, Dictionary queryParams, Object postBody, + String path, RestSharp.Method method, List> queryParams, Object postBody, Dictionary headerParams, Dictionary formParams, Dictionary fileParams, Dictionary pathParams, String contentType) @@ -174,6 +176,7 @@ namespace IO.Swagger.Client pathParams, contentType); // set timeout + RestClient.Timeout = Configuration.Timeout; // set user agent RestClient.UserAgent = Configuration.UserAgent; @@ -198,7 +201,7 @@ namespace IO.Swagger.Client /// Content type. /// The Task instance. public async System.Threading.Tasks.Task CallApiAsync( - String path, RestSharp.Method method, Dictionary queryParams, Object postBody, + String path, RestSharp.Method method, List> queryParams, Object postBody, Dictionary headerParams, Dictionary formParams, Dictionary fileParams, Dictionary pathParams, String contentType) @@ -286,6 +289,7 @@ namespace IO.Swagger.Client return response.RawBytes; } + // TODO: ? if (type.IsAssignableFrom(typeof(Stream))) if (type == typeof(Stream)) { if (headers != null) @@ -395,31 +399,29 @@ namespace IO.Swagger.Client /// /// Dynamically cast the object into target type. - /// Ref: http://stackoverflow.com/questions/4925718/c-dynamic-runtime-cast /// - /// Object to be casted - /// Target type + /// Object to be casted + /// Target type /// Casted object - public static dynamic ConvertType(dynamic source, Type dest) + public static dynamic ConvertType(dynamic fromObject, Type toObject) { - return Convert.ChangeType(source, dest); + return Convert.ChangeType(fromObject, toObject); } /// /// Convert stream to byte array - /// Credit/Ref: http://stackoverflow.com/a/221941/677735 /// - /// Input stream to be converted + /// Input stream to be converted /// Byte array - public static byte[] ReadAsBytes(Stream input) + public static byte[] ReadAsBytes(Stream inputStream) { - byte[] buffer = new byte[16*1024]; + byte[] buf = new byte[16*1024]; using (MemoryStream ms = new MemoryStream()) { - int read; - while ((read = input.Read(buffer, 0, buffer.Length)) > 0) + int count; + while ((count = inputStream.Read(buf, 0, buf.Length)) > 0) { - ms.Write(buffer, 0, read); + ms.Write(buf, 0, count); } return ms.ToArray(); } @@ -478,5 +480,39 @@ namespace IO.Swagger.Client return filename; } } + + /// + /// Convert params to key/value pairs. + /// Use collectionFormat to properly format lists and collections. + /// + /// Key name. + /// Value object. + /// A list of KeyValuePairs + public IEnumerable> ParameterToKeyValuePairs(string collectionFormat, string name, object value) + { + var parameters = new List>(); + + if (IsCollection(value) && collectionFormat == "multi") + { + var valueCollection = value as IEnumerable; + parameters.AddRange(from object item in valueCollection select new KeyValuePair(name, ParameterToString(item))); + } + else + { + parameters.Add(new KeyValuePair(name, ParameterToString(value))); + } + + return parameters; + } + + /// + /// Check if generic object is a collection. + /// + /// + /// True if object is a collection type + private static bool IsCollection(object value) + { + return value is IList || value is ICollection; + } } } diff --git a/samples/client/petstore-security-test/csharp/SwaggerClient/src/IO.Swagger/Client/Configuration.cs b/samples/client/petstore-security-test/csharp/SwaggerClient/src/IO.Swagger/Client/Configuration.cs index a816f96ecee..91cf1610fc4 100644 --- a/samples/client/petstore-security-test/csharp/SwaggerClient/src/IO.Swagger/Client/Configuration.cs +++ b/samples/client/petstore-security-test/csharp/SwaggerClient/src/IO.Swagger/Client/Configuration.cs @@ -10,6 +10,7 @@ using System; using System.Reflection; +using System.Collections.Concurrent; using System.Collections.Generic; using System.IO; using System.Linq; @@ -20,10 +21,147 @@ namespace IO.Swagger.Client /// /// Represents a set of configuration settings /// - public class Configuration + public class Configuration : IReadableConfiguration { + #region Constants + /// - /// Initializes a new instance of the Configuration class with different settings + /// Version of the package. + /// + /// Version of the package. + public const string Version = "1.0.0"; + + /// + /// Identifier for ISO 8601 DateTime Format + /// + /// See https://msdn.microsoft.com/en-us/library/az4se3k1(v=vs.110).aspx#Anchor_8 for more information. + // ReSharper disable once InconsistentNaming + public const string ISO8601_DATETIME_FORMAT = "o"; + + #endregion Constants + + #region Static Members + + private static readonly object GlobalConfigSync = new { }; + private static Configuration _globalConfiguration; + + /// + /// Default creation of exceptions for a given method name and response object + /// + public static readonly ExceptionFactory DefaultExceptionFactory = (methodName, response) => + { + var status = (int)response.StatusCode; + if (status >= 400) + { + return new ApiException(status, + string.Format("Error calling {0}: {1}", methodName, response.Content), + response.Content); + } + if (status == 0) + { + return new ApiException(status, + string.Format("Error calling {0}: {1}", methodName, response.ErrorMessage), response.ErrorMessage); + } + return null; + }; + + /// + /// Gets or sets the default Configuration. + /// + /// Configuration. + public static Configuration Default + { + get { return _globalConfiguration; } + set + { + lock (GlobalConfigSync) + { + _globalConfiguration = value; + } + } + } + + #endregion Static Members + + #region Private Members + + /// + /// Gets or sets the API key based on the authentication name. + /// + /// The API key. + private IDictionary _apiKey = null; + + /// + /// Gets or sets the prefix (e.g. Token) of the API key based on the authentication name. + /// + /// The prefix of the API key. + private IDictionary _apiKeyPrefix = null; + + private string _dateTimeFormat = ISO8601_DATETIME_FORMAT; + private string _tempFolderPath = Path.GetTempPath(); + + #endregion Private Members + + #region Constructors + + static Configuration() + { + _globalConfiguration = new GlobalConfiguration(); + } + + /// + /// Initializes a new instance of the class + /// + public Configuration() + { + UserAgent = "Swagger-Codegen/1.0.0/csharp"; + BasePath = "https://petstore.swagger.io *_/ ' \" =end - - \\r\\n \\n \\r/v2 *_/ ' \" =end - - \\r\\n \\n \\r"; + DefaultHeader = new ConcurrentDictionary(); + ApiKey = new ConcurrentDictionary(); + ApiKeyPrefix = new ConcurrentDictionary(); + + // Setting Timeout has side effects (forces ApiClient creation). + Timeout = 100000; + } + + /// + /// Initializes a new instance of the class + /// + public Configuration( + IDictionary defaultHeader, + IDictionary apiKey, + IDictionary apiKeyPrefix, + string basePath = "https://petstore.swagger.io *_/ ' \" =end - - \\r\\n \\n \\r/v2 *_/ ' \" =end - - \\r\\n \\n \\r") : this() + { + if (string.IsNullOrWhiteSpace(basePath)) + throw new ArgumentException("The provided basePath is invalid.", "basePath"); + if (defaultHeader == null) + throw new ArgumentNullException("defaultHeader"); + if (apiKey == null) + throw new ArgumentNullException("apiKey"); + if (apiKeyPrefix == null) + throw new ArgumentNullException("apiKeyPrefix"); + + BasePath = basePath; + + foreach (var keyValuePair in defaultHeader) + { + DefaultHeader.Add(keyValuePair); + } + + foreach (var keyValuePair in apiKey) + { + ApiKey.Add(keyValuePair); + } + + foreach (var keyValuePair in apiKeyPrefix) + { + ApiKeyPrefix.Add(keyValuePair); + } + } + + /// + /// Initializes a new instance of the class with different settings /// /// Api client /// Dictionary of default HTTP header @@ -36,129 +174,224 @@ namespace IO.Swagger.Client /// DateTime format string /// HTTP connection timeout (in milliseconds) /// HTTP user agent - public Configuration(ApiClient apiClient = null, - Dictionary defaultHeader = null, - string username = null, - string password = null, - string accessToken = null, - Dictionary apiKey = null, - Dictionary apiKeyPrefix = null, - string tempFolderPath = null, - string dateTimeFormat = null, - int timeout = 100000, - string userAgent = "Swagger-Codegen/1.0.0/csharp" - ) + [Obsolete("Use explicit object construction and setting of properties.", true)] + public Configuration( + // ReSharper disable UnusedParameter.Local + ApiClient apiClient = null, + IDictionary defaultHeader = null, + string username = null, + string password = null, + string accessToken = null, + IDictionary apiKey = null, + IDictionary apiKeyPrefix = null, + string tempFolderPath = null, + string dateTimeFormat = null, + int timeout = 100000, + string userAgent = "Swagger-Codegen/1.0.0/csharp" + // ReSharper restore UnusedParameter.Local + ) { - setApiClientUsingDefault(apiClient); - Username = username; - Password = password; - AccessToken = accessToken; - UserAgent = userAgent; - - if (defaultHeader != null) - DefaultHeader = defaultHeader; - if (apiKey != null) - ApiKey = apiKey; - if (apiKeyPrefix != null) - ApiKeyPrefix = apiKeyPrefix; - - TempFolderPath = tempFolderPath; - DateTimeFormat = dateTimeFormat; - Timeout = timeout; } /// /// Initializes a new instance of the Configuration class. /// /// Api client. + [Obsolete("This constructor caused unexpected sharing of static data. It is no longer supported.", true)] + // ReSharper disable once UnusedParameter.Local public Configuration(ApiClient apiClient) { - setApiClientUsingDefault(apiClient); + } - /// - /// Version of the package. - /// - /// Version of the package. - public const string Version = "1.0.0"; + #endregion Constructors - /// - /// Gets or sets the default Configuration. - /// - /// Configuration. - public static Configuration Default = new Configuration(); + #region Properties + + private ApiClient _apiClient = null; /// - /// Default creation of exceptions for a given method name and response object + /// Gets an instance of an ApiClient for this configuration /// - public static readonly ExceptionFactory DefaultExceptionFactory = (methodName, response) => + public virtual ApiClient ApiClient { - int status = (int) response.StatusCode; - if (status >= 400) return new ApiException(status, String.Format("Error calling {0}: {1}", methodName, response.Content), response.Content); - if (status == 0) return new ApiException(status, String.Format("Error calling {0}: {1}", methodName, response.ErrorMessage), response.ErrorMessage); - return null; - }; - - /// - /// Gets or sets the HTTP timeout (milliseconds) of ApiClient. Default to 100000 milliseconds. - /// - /// Timeout. - public int Timeout - { - get { return ApiClient.RestClient.Timeout; } - - set + get { - if (ApiClient != null) - ApiClient.RestClient.Timeout = value; + if (_apiClient == null) _apiClient = CreateApiClient(); + return _apiClient; } } + private String _basePath = null; /// - /// Gets or sets the default API client for making HTTP calls. + /// Gets or sets the base path for API access. /// - /// The API client. - public ApiClient ApiClient; - - /// - /// Set the ApiClient using Default or ApiClient instance. - /// - /// An instance of ApiClient. - /// - public void setApiClientUsingDefault (ApiClient apiClient = null) - { - if (apiClient == null) - { - if (Default != null && Default.ApiClient == null) - Default.ApiClient = new ApiClient(); - - ApiClient = Default != null ? Default.ApiClient : new ApiClient(); - } - else - { - if (Default != null && Default.ApiClient == null) - Default.ApiClient = apiClient; - - ApiClient = apiClient; + public virtual string BasePath { + get { return _basePath; } + set { + _basePath = value; + // pass-through to ApiClient if it's set. + if(_apiClient != null) { + _apiClient.RestClient.BaseUrl = new Uri(_basePath); + } } } - private Dictionary _defaultHeaderMap = new Dictionary(); - /// /// Gets or sets the default header. /// - public Dictionary DefaultHeader + public virtual IDictionary DefaultHeader { get; set; } + + /// + /// Gets or sets the HTTP timeout (milliseconds) of ApiClient. Default to 100000 milliseconds. + /// + public virtual int Timeout { - get { return _defaultHeaderMap; } + + get { return ApiClient.RestClient.Timeout; } + set { ApiClient.RestClient.Timeout = value; } + } + + /// + /// Gets or sets the HTTP user agent. + /// + /// Http user agent. + public virtual string UserAgent { get; set; } + + /// + /// Gets or sets the username (HTTP basic authentication). + /// + /// The username. + public virtual string Username { get; set; } + + /// + /// Gets or sets the password (HTTP basic authentication). + /// + /// The password. + public virtual string Password { get; set; } + + /// + /// Gets the API key with prefix. + /// + /// API key identifier (authentication scheme). + /// API key with prefix. + public string GetApiKeyWithPrefix(string apiKeyIdentifier) + { + var apiKeyValue = ""; + ApiKey.TryGetValue (apiKeyIdentifier, out apiKeyValue); + var apiKeyPrefix = ""; + if (ApiKeyPrefix.TryGetValue (apiKeyIdentifier, out apiKeyPrefix)) + return apiKeyPrefix + " " + apiKeyValue; + else + return apiKeyValue; + } + + /// + /// Gets or sets the access token for OAuth2 authentication. + /// + /// The access token. + public virtual string AccessToken { get; set; } + + /// + /// Gets or sets the temporary folder path to store the files downloaded from the server. + /// + /// Folder path. + public virtual string TempFolderPath + { + get { return _tempFolderPath; } set { - _defaultHeaderMap = value; + if (string.IsNullOrEmpty(value)) + { + // Possible breaking change since swagger-codegen 2.2.1, enforce a valid temporary path on set. + _tempFolderPath = Path.GetTempPath(); + return; + } + + // create the directory if it does not exist + if (!Directory.Exists(value)) + { + Directory.CreateDirectory(value); + } + + // check if the path contains directory separator at the end + if (value[value.Length - 1] == Path.DirectorySeparatorChar) + { + _tempFolderPath = value; + } + else + { + _tempFolderPath = value + Path.DirectorySeparatorChar; + } } } + /// + /// Gets or sets the the date time format used when serializing in the ApiClient + /// By default, it's set to ISO 8601 - "o", for others see: + /// https://msdn.microsoft.com/en-us/library/az4se3k1(v=vs.110).aspx + /// and https://msdn.microsoft.com/en-us/library/8kb3ddd4(v=vs.110).aspx + /// No validation is done to ensure that the string you're providing is valid + /// + /// The DateTimeFormat string + public virtual string DateTimeFormat + { + get { return _dateTimeFormat; } + set + { + if (string.IsNullOrEmpty(value)) + { + // Never allow a blank or null string, go back to the default + _dateTimeFormat = ISO8601_DATETIME_FORMAT; + return; + } + + // Caution, no validation when you choose date time format other than ISO 8601 + // Take a look at the above links + _dateTimeFormat = value; + } + } + + /// + /// Gets or sets the prefix (e.g. Token) of the API key based on the authentication name. + /// + /// The prefix of the API key. + public virtual IDictionary ApiKeyPrefix + { + get { return _apiKeyPrefix; } + set + { + if (value == null) + { + throw new InvalidOperationException("ApiKeyPrefix collection may not be null."); + } + _apiKeyPrefix = value; + } + } + + /// + /// Gets or sets the API key based on the authentication name. + /// + /// The API key. + public virtual IDictionary ApiKey + { + get { return _apiKey; } + set + { + if (value == null) + { + throw new InvalidOperationException("ApiKey collection may not be null."); + } + _apiKey = value; + } + } + + #endregion Properties + + #region Methods + /// /// Add default header. /// @@ -167,7 +400,31 @@ namespace IO.Swagger.Client /// public void AddDefaultHeader(string key, string value) { - _defaultHeaderMap[key] = value; + DefaultHeader[key] = value; + } + + /// + /// Creates a new based on this instance. + /// + /// + public ApiClient CreateApiClient() + { + return new ApiClient(BasePath) { Configuration = this }; + } + + + /// + /// Returns a string with essential information for debugging. + /// + public static String ToDebugReport() + { + String report = "C# SDK (IO.Swagger) Debug Report:\n"; + report += " OS: " + System.Environment.OSVersion + "\n"; + report += " .NET Framework Version: " + System.Environment.Version + "\n"; + report += " Version of the API: 1.0.0 *_/ ' \" =end - - \\r\\n \\n \\r\n"; + report += " SDK Package Version: 1.0.0\n"; + + return report; } /// @@ -191,144 +448,6 @@ namespace IO.Swagger.Client ApiKeyPrefix[key] = value; } - /// - /// Gets or sets the HTTP user agent. - /// - /// Http user agent. - public String UserAgent { get; set; } - - /// - /// Gets or sets the username (HTTP basic authentication). - /// - /// The username. - public String Username { get; set; } - - /// - /// Gets or sets the password (HTTP basic authentication). - /// - /// The password. - public String Password { get; set; } - - /// - /// Gets or sets the access token for OAuth2 authentication. - /// - /// The access token. - public String AccessToken { get; set; } - - /// - /// Gets or sets the API key based on the authentication name. - /// - /// The API key. - public Dictionary ApiKey = new Dictionary(); - - /// - /// Gets or sets the prefix (e.g. Token) of the API key based on the authentication name. - /// - /// The prefix of the API key. - public Dictionary ApiKeyPrefix = new Dictionary(); - - /// - /// Get the API key with prefix. - /// - /// API key identifier (authentication scheme). - /// API key with prefix. - public string GetApiKeyWithPrefix (string apiKeyIdentifier) - { - var apiKeyValue = ""; - ApiKey.TryGetValue (apiKeyIdentifier, out apiKeyValue); - var apiKeyPrefix = ""; - if (ApiKeyPrefix.TryGetValue (apiKeyIdentifier, out apiKeyPrefix)) - return apiKeyPrefix + " " + apiKeyValue; - else - return apiKeyValue; - } - - private string _tempFolderPath; - - /// - /// Gets or sets the temporary folder path to store the files downloaded from the server. - /// - /// Folder path. - public String TempFolderPath - { - get - { - // default to Path.GetTempPath() if _tempFolderPath is not set - if (String.IsNullOrEmpty(_tempFolderPath)) - { - _tempFolderPath = Path.GetTempPath(); - } - return _tempFolderPath; - } - - set - { - if (String.IsNullOrEmpty(value)) - { - _tempFolderPath = value; - return; - } - - // create the directory if it does not exist - if (!Directory.Exists(value)) - Directory.CreateDirectory(value); - - // check if the path contains directory separator at the end - if (value[value.Length - 1] == Path.DirectorySeparatorChar) - _tempFolderPath = value; - else - _tempFolderPath = value + Path.DirectorySeparatorChar; - } - } - - private const string ISO8601_DATETIME_FORMAT = "o"; - - private string _dateTimeFormat = ISO8601_DATETIME_FORMAT; - - /// - /// Gets or sets the the date time format used when serializing in the ApiClient - /// By default, it's set to ISO 8601 - "o", for others see: - /// https://msdn.microsoft.com/en-us/library/az4se3k1(v=vs.110).aspx - /// and https://msdn.microsoft.com/en-us/library/8kb3ddd4(v=vs.110).aspx - /// No validation is done to ensure that the string you're providing is valid - /// - /// The DateTimeFormat string - public String DateTimeFormat - { - get - { - return _dateTimeFormat; - } - set - { - if (string.IsNullOrEmpty(value)) - { - // Never allow a blank or null string, go back to the default - _dateTimeFormat = ISO8601_DATETIME_FORMAT; - return; - } - - // Caution, no validation when you choose date time format other than ISO 8601 - // Take a look at the above links - _dateTimeFormat = value; - } - } - - /// - /// Returns a string with essential information for debugging. - /// - public static String ToDebugReport() - { - String report = "C# SDK (IO.Swagger) Debug Report:\n"; - report += " OS: " + Environment.OSVersion + "\n"; - report += " .NET Framework Version: " + Assembly - .GetExecutingAssembly() - .GetReferencedAssemblies() - .Where(x => x.Name == "System.Core").First().Version.ToString() + "\n"; - report += " Version of the API: 1.0.0 *_/ ' \" =end - - \\r\\n \\n \\r\n"; - report += " SDK Package Version: 1.0.0\n"; - - return report; - } + #endregion Methods } } diff --git a/samples/client/petstore-security-test/csharp/SwaggerClient/src/IO.Swagger/Client/GlobalConfiguration.cs b/samples/client/petstore-security-test/csharp/SwaggerClient/src/IO.Swagger/Client/GlobalConfiguration.cs new file mode 100644 index 00000000000..a4878529d8a --- /dev/null +++ b/samples/client/petstore-security-test/csharp/SwaggerClient/src/IO.Swagger/Client/GlobalConfiguration.cs @@ -0,0 +1,34 @@ +/* + * Swagger Petstore *_/ ' \" =end - - \\r\\n \\n \\r + * + * This spec is mainly for testing Petstore server and contains fake endpoints, models. Please do not use this for any other purpose. Special characters: \" \\ *_/ ' \" =end - - + * + * OpenAPI spec version: 1.0.0 *_/ ' \" =end - - \\r\\n \\n \\r + * Contact: apiteam@swagger.io *_/ ' \" =end - - \\r\\n \\n \\r + * Generated by: https://github.com/swagger-api/swagger-codegen.git + */ + + +using System; +using System.Reflection; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading; + +namespace IO.Swagger.Client +{ + /// + /// provides a compile-time extension point for globally configuring + /// API Clients. + /// + /// + /// A customized implementation via partial class may reside in another file and may + /// be excluded from automatic generation via a .swagger-codegen-ignore file. + /// + public partial class GlobalConfiguration : Configuration + { + + } +} \ No newline at end of file diff --git a/samples/client/petstore-security-test/csharp/SwaggerClient/src/IO.Swagger/Client/IReadableConfiguration.cs b/samples/client/petstore-security-test/csharp/SwaggerClient/src/IO.Swagger/Client/IReadableConfiguration.cs new file mode 100644 index 00000000000..f0ebce70672 --- /dev/null +++ b/samples/client/petstore-security-test/csharp/SwaggerClient/src/IO.Swagger/Client/IReadableConfiguration.cs @@ -0,0 +1,94 @@ +/* + * Swagger Petstore *_/ ' \" =end - - \\r\\n \\n \\r + * + * This spec is mainly for testing Petstore server and contains fake endpoints, models. Please do not use this for any other purpose. Special characters: \" \\ *_/ ' \" =end - - + * + * OpenAPI spec version: 1.0.0 *_/ ' \" =end - - \\r\\n \\n \\r + * Contact: apiteam@swagger.io *_/ ' \" =end - - \\r\\n \\n \\r + * Generated by: https://github.com/swagger-api/swagger-codegen.git + */ + + +using System.Collections.Generic; + +namespace IO.Swagger.Client +{ + /// + /// Represents a readable-only configuration contract. + /// + public interface IReadableConfiguration + { + /// + /// Gets the access token. + /// + /// Access token. + string AccessToken { get; } + + /// + /// Gets the API key. + /// + /// API key. + IDictionary ApiKey { get; } + + /// + /// Gets the API key prefix. + /// + /// API key prefix. + IDictionary ApiKeyPrefix { get; } + + /// + /// Gets the base path. + /// + /// Base path. + string BasePath { get; } + + /// + /// Gets the date time format. + /// + /// Date time foramt. + string DateTimeFormat { get; } + + /// + /// Gets the default header. + /// + /// Default header. + IDictionary DefaultHeader { get; } + + /// + /// Gets the temp folder path. + /// + /// Temp folder path. + string TempFolderPath { get; } + + /// + /// Gets the HTTP connection timeout (in milliseconds) + /// + /// HTTP connection timeout. + int Timeout { get; } + + /// + /// Gets the user agent. + /// + /// User agent. + string UserAgent { get; } + + /// + /// Gets the username. + /// + /// Username. + string Username { get; } + + /// + /// Gets the password. + /// + /// Password. + string Password { get; } + + /// + /// Gets the API key with prefix. + /// + /// API key identifier (authentication scheme). + /// API key with prefix. + string GetApiKeyWithPrefix(string apiKeyIdentifier); + } +} diff --git a/samples/client/petstore-security-test/csharp/SwaggerClient/src/IO.Swagger/Client/JsonSubTypes.cs b/samples/client/petstore-security-test/csharp/SwaggerClient/src/IO.Swagger/Client/JsonSubTypes.cs new file mode 100644 index 00000000000..3a6da091b78 --- /dev/null +++ b/samples/client/petstore-security-test/csharp/SwaggerClient/src/IO.Swagger/Client/JsonSubTypes.cs @@ -0,0 +1,272 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; + +namespace JsonSubTypes +{ + // Copied from project https://github.com/manuc66/JsonSubTypes + // https://raw.githubusercontent.com/manuc66/JsonSubTypes/07403192ea3f4959f6d42f5966ac56ceb0d6095b/JsonSubTypes/JsonSubtypes.cs + + public class JsonSubtypes : JsonConverter + { + [AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface, AllowMultiple = true)] + public class KnownSubTypeAttribute : Attribute + { + public Type SubType { get; private set; } + public object AssociatedValue { get; private set; } + + public KnownSubTypeAttribute(Type subType, object associatedValue) + { + SubType = subType; + AssociatedValue = associatedValue; + } + } + [AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface, AllowMultiple = true)] + public class KnownSubTypeWithPropertyAttribute : Attribute + { + public Type SubType { get; private set; } + public string PropertyName { get; private set; } + + public KnownSubTypeWithPropertyAttribute(Type subType, string propertyName) + { + SubType = subType; + PropertyName = propertyName; + } + } + + private readonly string _typeMappingPropertyName; + + private bool _isInsideRead; + private JsonReader _reader; + + public override bool CanRead + { + get + { + if (!_isInsideRead) + return true; + + return !string.IsNullOrEmpty(_reader.Path); + } + } + + public sealed override bool CanWrite + { + get { return false; } + } + + public JsonSubtypes() + { + } + + public JsonSubtypes(string typeMappingPropertyName) + { + _typeMappingPropertyName = typeMappingPropertyName; + } + + public override bool CanConvert(Type objectType) + { + return _typeMappingPropertyName != null; + } + + public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) + { + throw new NotImplementedException(); + } + + public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) + { + if (reader.TokenType == JsonToken.Comment) + reader.Read(); + + switch (reader.TokenType) + { + case JsonToken.Null: + return null; + case JsonToken.StartArray: + return ReadArray(reader, objectType, serializer); + case JsonToken.StartObject: + return ReadObject(reader, objectType, serializer); + default: + throw new Exception("Array: Unrecognized token: " + reader.TokenType); + } + } + + private IList ReadArray(JsonReader reader, Type targetType, JsonSerializer serializer) + { + var elementType = GetElementType(targetType); + + var list = CreateCompatibleList(targetType, elementType); + + while (reader.TokenType != JsonToken.EndArray && reader.Read()) + { + switch (reader.TokenType) + { + case JsonToken.Null: + list.Add(reader.Value); + break; + case JsonToken.Comment: + break; + case JsonToken.StartObject: + list.Add(ReadObject(reader, elementType, serializer)); + break; + case JsonToken.EndArray: + break; + default: + throw new Exception("Array: Unrecognized token: " + reader.TokenType); + } + } + if (targetType.IsArray) + { + var array = Array.CreateInstance(targetType.GetElementType(), list.Count); + list.CopyTo(array, 0); + list = array; + } + return list; + } + + private static IList CreateCompatibleList(Type targetContainerType, Type elementType) + { + IList list; + if (targetContainerType.IsArray || targetContainerType.GetTypeInfo().IsAbstract) + { + list = (IList)Activator.CreateInstance(typeof(List<>).MakeGenericType(elementType)); + } + else + { + list = (IList)Activator.CreateInstance(targetContainerType); + } + return list; + } + + private static Type GetElementType(Type arrayOrGenericContainer) + { + Type elementType; + if (arrayOrGenericContainer.IsArray) + { + elementType = arrayOrGenericContainer.GetElementType(); + } + else + { + elementType = arrayOrGenericContainer.GenericTypeArguments[0]; + } + return elementType; + } + + private object ReadObject(JsonReader reader, Type objectType, JsonSerializer serializer) + { + var jObject = JObject.Load(reader); + + var targetType = GetType(jObject, objectType) ?? objectType; + + return _ReadJson(CreateAnotherReader(jObject, reader), targetType, null, serializer); + } + + private static JsonReader CreateAnotherReader(JObject jObject, JsonReader reader) + { + var jObjectReader = jObject.CreateReader(); + jObjectReader.Culture = reader.Culture; + jObjectReader.CloseInput = reader.CloseInput; + jObjectReader.SupportMultipleContent = reader.SupportMultipleContent; + jObjectReader.DateTimeZoneHandling = reader.DateTimeZoneHandling; + jObjectReader.FloatParseHandling = reader.FloatParseHandling; + jObjectReader.DateFormatString = reader.DateFormatString; + jObjectReader.DateParseHandling = reader.DateParseHandling; + return jObjectReader; + } + + public Type GetType(JObject jObject, Type parentType) + { + if (_typeMappingPropertyName == null) + { + return GetTypeByPropertyPresence(jObject, parentType); + } + return GetTypeFromDiscriminatorValue(jObject, parentType); + } + + private static Type GetTypeByPropertyPresence(JObject jObject, Type parentType) + { + foreach (var type in parentType.GetTypeInfo().GetCustomAttributes()) + { + JToken ignore; + if (jObject.TryGetValue(type.PropertyName, out ignore)) + { + return type.SubType; + } + } + return null; + } + + private Type GetTypeFromDiscriminatorValue(JObject jObject, Type parentType) + { + JToken jToken; + if (!jObject.TryGetValue(_typeMappingPropertyName, out jToken)) return null; + + var discriminatorValue = jToken.ToObject(); + if (discriminatorValue == null) return null; + + var typeMapping = GetSubTypeMapping(parentType); + if (typeMapping.Any()) + { + return GetTypeFromMapping(typeMapping, discriminatorValue); + } + return GetTypeByName(discriminatorValue as string, parentType); + } + + private static Type GetTypeByName(string typeName, Type parentType) + { + if (typeName == null) + return null; + + var insideAssembly = parentType.GetTypeInfo().Assembly; + + var typeByName = insideAssembly.GetType(typeName); + if (typeByName == null) + { + var searchLocation = parentType.FullName.Substring(0, parentType.FullName.Length - parentType.Name.Length); + typeByName = insideAssembly.GetType(searchLocation + typeName, false, true); + } + return typeByName; + } + + private static Type GetTypeFromMapping(IReadOnlyDictionary typeMapping, object discriminatorValue) + { + var targetlookupValueType = typeMapping.First().Key.GetType(); + var lookupValue = ConvertJsonValueToType(discriminatorValue, targetlookupValueType); + + Type targetType; + return typeMapping.TryGetValue(lookupValue, out targetType) ? targetType : null; + } + + private static Dictionary GetSubTypeMapping(Type type) + { + return type.GetTypeInfo().GetCustomAttributes().ToDictionary(x => x.AssociatedValue, x => x.SubType); + } + + private static object ConvertJsonValueToType(object objectType, Type targetlookupValueType) + { + if (targetlookupValueType.GetTypeInfo().IsEnum) + return Enum.ToObject(targetlookupValueType, objectType); + + return Convert.ChangeType(objectType, targetlookupValueType); + } + + protected object _ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) + { + _reader = reader; + _isInsideRead = true; + try + { + return serializer.Deserialize(reader, objectType); + } + finally + { + _isInsideRead = false; + } + } + } +} diff --git a/samples/client/petstore-security-test/csharp/SwaggerClient/src/IO.Swagger/Model/ModelReturn.cs b/samples/client/petstore-security-test/csharp/SwaggerClient/src/IO.Swagger/Model/ModelReturn.cs index 13d7c9052e5..e9e53a12799 100644 --- a/samples/client/petstore-security-test/csharp/SwaggerClient/src/IO.Swagger/Model/ModelReturn.cs +++ b/samples/client/petstore-security-test/csharp/SwaggerClient/src/IO.Swagger/Model/ModelReturn.cs @@ -71,30 +71,28 @@ namespace IO.Swagger.Model /// /// Returns true if objects are equal /// - /// Object to be compared + /// Object to be compared /// Boolean - public override bool Equals(object obj) + public override bool Equals(object input) { - // credit: http://stackoverflow.com/a/10454552/677735 - return this.Equals(obj as ModelReturn); + return this.Equals(input as ModelReturn); } /// /// Returns true if ModelReturn instances are equal /// - /// Instance of ModelReturn to be compared + /// Instance of ModelReturn to be compared /// Boolean - public bool Equals(ModelReturn other) + public bool Equals(ModelReturn input) { - // credit: http://stackoverflow.com/a/10454552/677735 - if (other == null) + if (input == null) return false; return ( - this._Return == other._Return || - this._Return != null && - this._Return.Equals(other._Return) + this._Return == input._Return || + (this._Return != null && + this._Return.Equals(input._Return)) ); } @@ -104,14 +102,12 @@ namespace IO.Swagger.Model /// Hash code public override int GetHashCode() { - // credit: http://stackoverflow.com/a/263416/677735 unchecked // Overflow is fine, just wrap { - int hash = 41; - // Suitable nullity checks etc, of course :) + int hashCode = 41; if (this._Return != null) - hash = hash * 59 + this._Return.GetHashCode(); - return hash; + hashCode = hashCode * 59 + this._Return.GetHashCode(); + return hashCode; } } diff --git a/samples/client/petstore/csharp/SwaggerClient/IO.Swagger.sln b/samples/client/petstore/csharp/SwaggerClient/IO.Swagger.sln index 4b433720f5c..05f9d7c8586 100644 --- a/samples/client/petstore/csharp/SwaggerClient/IO.Swagger.sln +++ b/samples/client/petstore/csharp/SwaggerClient/IO.Swagger.sln @@ -7,21 +7,21 @@ EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "IO.Swagger.Test", "src\IO.Swagger.Test\IO.Swagger.Test.csproj", "{19F1DEBC-DE5E-4517-8062-F000CD499087}" EndProject Global -GlobalSection(SolutionConfigurationPlatforms) = preSolution -Debug|Any CPU = Debug|Any CPU -Release|Any CPU = Release|Any CPU -EndGlobalSection -GlobalSection(ProjectConfigurationPlatforms) = postSolution -{321C8C3F-0156-40C1-AE42-D59761FB9B6C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU -{321C8C3F-0156-40C1-AE42-D59761FB9B6C}.Debug|Any CPU.Build.0 = Debug|Any CPU -{321C8C3F-0156-40C1-AE42-D59761FB9B6C}.Release|Any CPU.ActiveCfg = Release|Any CPU -{321C8C3F-0156-40C1-AE42-D59761FB9B6C}.Release|Any CPU.Build.0 = Release|Any CPU -{19F1DEBC-DE5E-4517-8062-F000CD499087}.Debug|Any CPU.ActiveCfg = Debug|Any CPU -{19F1DEBC-DE5E-4517-8062-F000CD499087}.Debug|Any CPU.Build.0 = Debug|Any CPU -{19F1DEBC-DE5E-4517-8062-F000CD499087}.Release|Any CPU.ActiveCfg = Release|Any CPU -{19F1DEBC-DE5E-4517-8062-F000CD499087}.Release|Any CPU.Build.0 = Release|Any CPU -EndGlobalSection -GlobalSection(SolutionProperties) = preSolution -HideSolutionNode = FALSE -EndGlobalSection + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {321C8C3F-0156-40C1-AE42-D59761FB9B6C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {321C8C3F-0156-40C1-AE42-D59761FB9B6C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {321C8C3F-0156-40C1-AE42-D59761FB9B6C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {321C8C3F-0156-40C1-AE42-D59761FB9B6C}.Release|Any CPU.Build.0 = Release|Any CPU + {19F1DEBC-DE5E-4517-8062-F000CD499087}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {19F1DEBC-DE5E-4517-8062-F000CD499087}.Debug|Any CPU.Build.0 = Debug|Any CPU + {19F1DEBC-DE5E-4517-8062-F000CD499087}.Release|Any CPU.ActiveCfg = Release|Any CPU + {19F1DEBC-DE5E-4517-8062-F000CD499087}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection EndGlobal \ No newline at end of file diff --git a/samples/client/petstore/csharp/SwaggerClient/src/IO.Swagger.Test/Model/AnimalTests.cs b/samples/client/petstore/csharp/SwaggerClient/src/IO.Swagger.Test/Model/AnimalTests.cs index 59cd4d76d68..29c668f12ab 100644 --- a/samples/client/petstore/csharp/SwaggerClient/src/IO.Swagger.Test/Model/AnimalTests.cs +++ b/samples/client/petstore/csharp/SwaggerClient/src/IO.Swagger.Test/Model/AnimalTests.cs @@ -8,6 +8,7 @@ using IO.Swagger.Api; using IO.Swagger.Model; using IO.Swagger.Client; using System.Reflection; +using Newtonsoft.Json; namespace IO.Swagger.Test { @@ -50,6 +51,25 @@ namespace IO.Swagger.Test Assert.IsInstanceOfType(typeof(Animal), instance, "instance is a Animal"); } + /// + /// Test deserialize a Dog from type Animal + /// + [Test] + public void DogDeserializeFromAnimalTest() + { + // TODO uncomment below to test deserialize a Dog from type Animal + //Assert.IsInstanceOf(JsonConvert.DeserializeObject(new Dog().ToJson())); + } + /// + /// Test deserialize a Cat from type Animal + /// + [Test] + public void CatDeserializeFromAnimalTest() + { + // TODO uncomment below to test deserialize a Cat from type Animal + //Assert.IsInstanceOf(JsonConvert.DeserializeObject(new Cat().ToJson())); + } + /// /// Test the property 'ClassName' /// diff --git a/samples/client/petstore/csharp/SwaggerClient/src/IO.Swagger/Client/JsonSubTypes.cs b/samples/client/petstore/csharp/SwaggerClient/src/IO.Swagger/Client/JsonSubTypes.cs new file mode 100644 index 00000000000..3a6da091b78 --- /dev/null +++ b/samples/client/petstore/csharp/SwaggerClient/src/IO.Swagger/Client/JsonSubTypes.cs @@ -0,0 +1,272 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; + +namespace JsonSubTypes +{ + // Copied from project https://github.com/manuc66/JsonSubTypes + // https://raw.githubusercontent.com/manuc66/JsonSubTypes/07403192ea3f4959f6d42f5966ac56ceb0d6095b/JsonSubTypes/JsonSubtypes.cs + + public class JsonSubtypes : JsonConverter + { + [AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface, AllowMultiple = true)] + public class KnownSubTypeAttribute : Attribute + { + public Type SubType { get; private set; } + public object AssociatedValue { get; private set; } + + public KnownSubTypeAttribute(Type subType, object associatedValue) + { + SubType = subType; + AssociatedValue = associatedValue; + } + } + [AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface, AllowMultiple = true)] + public class KnownSubTypeWithPropertyAttribute : Attribute + { + public Type SubType { get; private set; } + public string PropertyName { get; private set; } + + public KnownSubTypeWithPropertyAttribute(Type subType, string propertyName) + { + SubType = subType; + PropertyName = propertyName; + } + } + + private readonly string _typeMappingPropertyName; + + private bool _isInsideRead; + private JsonReader _reader; + + public override bool CanRead + { + get + { + if (!_isInsideRead) + return true; + + return !string.IsNullOrEmpty(_reader.Path); + } + } + + public sealed override bool CanWrite + { + get { return false; } + } + + public JsonSubtypes() + { + } + + public JsonSubtypes(string typeMappingPropertyName) + { + _typeMappingPropertyName = typeMappingPropertyName; + } + + public override bool CanConvert(Type objectType) + { + return _typeMappingPropertyName != null; + } + + public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) + { + throw new NotImplementedException(); + } + + public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) + { + if (reader.TokenType == JsonToken.Comment) + reader.Read(); + + switch (reader.TokenType) + { + case JsonToken.Null: + return null; + case JsonToken.StartArray: + return ReadArray(reader, objectType, serializer); + case JsonToken.StartObject: + return ReadObject(reader, objectType, serializer); + default: + throw new Exception("Array: Unrecognized token: " + reader.TokenType); + } + } + + private IList ReadArray(JsonReader reader, Type targetType, JsonSerializer serializer) + { + var elementType = GetElementType(targetType); + + var list = CreateCompatibleList(targetType, elementType); + + while (reader.TokenType != JsonToken.EndArray && reader.Read()) + { + switch (reader.TokenType) + { + case JsonToken.Null: + list.Add(reader.Value); + break; + case JsonToken.Comment: + break; + case JsonToken.StartObject: + list.Add(ReadObject(reader, elementType, serializer)); + break; + case JsonToken.EndArray: + break; + default: + throw new Exception("Array: Unrecognized token: " + reader.TokenType); + } + } + if (targetType.IsArray) + { + var array = Array.CreateInstance(targetType.GetElementType(), list.Count); + list.CopyTo(array, 0); + list = array; + } + return list; + } + + private static IList CreateCompatibleList(Type targetContainerType, Type elementType) + { + IList list; + if (targetContainerType.IsArray || targetContainerType.GetTypeInfo().IsAbstract) + { + list = (IList)Activator.CreateInstance(typeof(List<>).MakeGenericType(elementType)); + } + else + { + list = (IList)Activator.CreateInstance(targetContainerType); + } + return list; + } + + private static Type GetElementType(Type arrayOrGenericContainer) + { + Type elementType; + if (arrayOrGenericContainer.IsArray) + { + elementType = arrayOrGenericContainer.GetElementType(); + } + else + { + elementType = arrayOrGenericContainer.GenericTypeArguments[0]; + } + return elementType; + } + + private object ReadObject(JsonReader reader, Type objectType, JsonSerializer serializer) + { + var jObject = JObject.Load(reader); + + var targetType = GetType(jObject, objectType) ?? objectType; + + return _ReadJson(CreateAnotherReader(jObject, reader), targetType, null, serializer); + } + + private static JsonReader CreateAnotherReader(JObject jObject, JsonReader reader) + { + var jObjectReader = jObject.CreateReader(); + jObjectReader.Culture = reader.Culture; + jObjectReader.CloseInput = reader.CloseInput; + jObjectReader.SupportMultipleContent = reader.SupportMultipleContent; + jObjectReader.DateTimeZoneHandling = reader.DateTimeZoneHandling; + jObjectReader.FloatParseHandling = reader.FloatParseHandling; + jObjectReader.DateFormatString = reader.DateFormatString; + jObjectReader.DateParseHandling = reader.DateParseHandling; + return jObjectReader; + } + + public Type GetType(JObject jObject, Type parentType) + { + if (_typeMappingPropertyName == null) + { + return GetTypeByPropertyPresence(jObject, parentType); + } + return GetTypeFromDiscriminatorValue(jObject, parentType); + } + + private static Type GetTypeByPropertyPresence(JObject jObject, Type parentType) + { + foreach (var type in parentType.GetTypeInfo().GetCustomAttributes()) + { + JToken ignore; + if (jObject.TryGetValue(type.PropertyName, out ignore)) + { + return type.SubType; + } + } + return null; + } + + private Type GetTypeFromDiscriminatorValue(JObject jObject, Type parentType) + { + JToken jToken; + if (!jObject.TryGetValue(_typeMappingPropertyName, out jToken)) return null; + + var discriminatorValue = jToken.ToObject(); + if (discriminatorValue == null) return null; + + var typeMapping = GetSubTypeMapping(parentType); + if (typeMapping.Any()) + { + return GetTypeFromMapping(typeMapping, discriminatorValue); + } + return GetTypeByName(discriminatorValue as string, parentType); + } + + private static Type GetTypeByName(string typeName, Type parentType) + { + if (typeName == null) + return null; + + var insideAssembly = parentType.GetTypeInfo().Assembly; + + var typeByName = insideAssembly.GetType(typeName); + if (typeByName == null) + { + var searchLocation = parentType.FullName.Substring(0, parentType.FullName.Length - parentType.Name.Length); + typeByName = insideAssembly.GetType(searchLocation + typeName, false, true); + } + return typeByName; + } + + private static Type GetTypeFromMapping(IReadOnlyDictionary typeMapping, object discriminatorValue) + { + var targetlookupValueType = typeMapping.First().Key.GetType(); + var lookupValue = ConvertJsonValueToType(discriminatorValue, targetlookupValueType); + + Type targetType; + return typeMapping.TryGetValue(lookupValue, out targetType) ? targetType : null; + } + + private static Dictionary GetSubTypeMapping(Type type) + { + return type.GetTypeInfo().GetCustomAttributes().ToDictionary(x => x.AssociatedValue, x => x.SubType); + } + + private static object ConvertJsonValueToType(object objectType, Type targetlookupValueType) + { + if (targetlookupValueType.GetTypeInfo().IsEnum) + return Enum.ToObject(targetlookupValueType, objectType); + + return Convert.ChangeType(objectType, targetlookupValueType); + } + + protected object _ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) + { + _reader = reader; + _isInsideRead = true; + try + { + return serializer.Deserialize(reader, objectType); + } + finally + { + _isInsideRead = false; + } + } + } +} diff --git a/samples/client/petstore/csharp/SwaggerClient/src/IO.Swagger/Model/AdditionalPropertiesClass.cs b/samples/client/petstore/csharp/SwaggerClient/src/IO.Swagger/Model/AdditionalPropertiesClass.cs index f1b63aca5d2..ad54e625864 100644 --- a/samples/client/petstore/csharp/SwaggerClient/src/IO.Swagger/Model/AdditionalPropertiesClass.cs +++ b/samples/client/petstore/csharp/SwaggerClient/src/IO.Swagger/Model/AdditionalPropertiesClass.cs @@ -99,13 +99,13 @@ namespace IO.Swagger.Model return ( this.MapProperty == input.MapProperty || - (this.MapProperty != null && - this.MapProperty.SequenceEqual(input.MapProperty)) + this.MapProperty != null && + this.MapProperty.SequenceEqual(input.MapProperty) ) && ( this.MapOfMapProperty == input.MapOfMapProperty || - (this.MapOfMapProperty != null && - this.MapOfMapProperty.SequenceEqual(input.MapOfMapProperty)) + this.MapOfMapProperty != null && + this.MapOfMapProperty.SequenceEqual(input.MapOfMapProperty) ); } diff --git a/samples/client/petstore/csharp/SwaggerClient/src/IO.Swagger/Model/Animal.cs b/samples/client/petstore/csharp/SwaggerClient/src/IO.Swagger/Model/Animal.cs index 2bbcf7d81e1..9b44060fb85 100644 --- a/samples/client/petstore/csharp/SwaggerClient/src/IO.Swagger/Model/Animal.cs +++ b/samples/client/petstore/csharp/SwaggerClient/src/IO.Swagger/Model/Animal.cs @@ -19,6 +19,7 @@ using System.Collections.ObjectModel; using System.Runtime.Serialization; using Newtonsoft.Json; using Newtonsoft.Json.Converters; +using JsonSubTypes; using System.ComponentModel.DataAnnotations; using SwaggerDateConverter = IO.Swagger.Client.SwaggerDateConverter; @@ -28,6 +29,9 @@ namespace IO.Swagger.Model /// Animal /// [DataContract] + [JsonConverter(typeof(JsonSubtypes), "className")] + [JsonSubtypes.KnownSubType(typeof(Dog), "Dog")] + [JsonSubtypes.KnownSubType(typeof(Cat), "Cat")] public partial class Animal : IEquatable, IValidatableObject { /// @@ -92,7 +96,7 @@ namespace IO.Swagger.Model /// Returns the JSON string presentation of the object /// /// JSON string presentation of the object - public string ToJson() + public virtual string ToJson() { return JsonConvert.SerializeObject(this, Formatting.Indented); } @@ -153,6 +157,16 @@ namespace IO.Swagger.Model /// Validation context /// Validation Result IEnumerable IValidatableObject.Validate(ValidationContext validationContext) + { + return this.BaseValidate(validationContext); + } + + /// + /// To validate all properties of the instance + /// + /// Validation context + /// Validation Result + protected IEnumerable BaseValidate(ValidationContext validationContext) { yield break; } diff --git a/samples/client/petstore/csharp/SwaggerClient/src/IO.Swagger/Model/AnimalFarm.cs b/samples/client/petstore/csharp/SwaggerClient/src/IO.Swagger/Model/AnimalFarm.cs index 4f21f19b8db..50767b53ec2 100644 --- a/samples/client/petstore/csharp/SwaggerClient/src/IO.Swagger/Model/AnimalFarm.cs +++ b/samples/client/petstore/csharp/SwaggerClient/src/IO.Swagger/Model/AnimalFarm.cs @@ -34,7 +34,7 @@ namespace IO.Swagger.Model /// Initializes a new instance of the class. /// [JsonConstructorAttribute] - public AnimalFarm() + public AnimalFarm() : base() { } @@ -46,6 +46,7 @@ namespace IO.Swagger.Model { var sb = new StringBuilder(); sb.Append("class AnimalFarm {\n"); + sb.Append(" ").Append(base.ToString().Replace("\n", "\n ")).Append("\n"); sb.Append("}\n"); return sb.ToString(); } @@ -54,7 +55,7 @@ namespace IO.Swagger.Model /// Returns the JSON string presentation of the object /// /// JSON string presentation of the object - public new string ToJson() + public string ToJson() { return JsonConvert.SerializeObject(this, Formatting.Indented); } @@ -79,7 +80,7 @@ namespace IO.Swagger.Model if (input == null) return false; - return false; + return base.Equals(input); } /// @@ -90,7 +91,7 @@ namespace IO.Swagger.Model { unchecked // Overflow is fine, just wrap { - int hashCode = 41; + int hashCode = base.GetHashCode(); return hashCode; } } diff --git a/samples/client/petstore/csharp/SwaggerClient/src/IO.Swagger/Model/ArrayOfArrayOfNumberOnly.cs b/samples/client/petstore/csharp/SwaggerClient/src/IO.Swagger/Model/ArrayOfArrayOfNumberOnly.cs index 01895993d7a..048483cdf48 100644 --- a/samples/client/petstore/csharp/SwaggerClient/src/IO.Swagger/Model/ArrayOfArrayOfNumberOnly.cs +++ b/samples/client/petstore/csharp/SwaggerClient/src/IO.Swagger/Model/ArrayOfArrayOfNumberOnly.cs @@ -90,8 +90,8 @@ namespace IO.Swagger.Model return ( this.ArrayArrayNumber == input.ArrayArrayNumber || - (this.ArrayArrayNumber != null && - this.ArrayArrayNumber.SequenceEqual(input.ArrayArrayNumber)) + this.ArrayArrayNumber != null && + this.ArrayArrayNumber.SequenceEqual(input.ArrayArrayNumber) ); } diff --git a/samples/client/petstore/csharp/SwaggerClient/src/IO.Swagger/Model/ArrayOfNumberOnly.cs b/samples/client/petstore/csharp/SwaggerClient/src/IO.Swagger/Model/ArrayOfNumberOnly.cs index d0389f21a38..ccff9ee3f0e 100644 --- a/samples/client/petstore/csharp/SwaggerClient/src/IO.Swagger/Model/ArrayOfNumberOnly.cs +++ b/samples/client/petstore/csharp/SwaggerClient/src/IO.Swagger/Model/ArrayOfNumberOnly.cs @@ -90,8 +90,8 @@ namespace IO.Swagger.Model return ( this.ArrayNumber == input.ArrayNumber || - (this.ArrayNumber != null && - this.ArrayNumber.SequenceEqual(input.ArrayNumber)) + this.ArrayNumber != null && + this.ArrayNumber.SequenceEqual(input.ArrayNumber) ); } diff --git a/samples/client/petstore/csharp/SwaggerClient/src/IO.Swagger/Model/ArrayTest.cs b/samples/client/petstore/csharp/SwaggerClient/src/IO.Swagger/Model/ArrayTest.cs index 9f2a062a36f..66cca739d5e 100644 --- a/samples/client/petstore/csharp/SwaggerClient/src/IO.Swagger/Model/ArrayTest.cs +++ b/samples/client/petstore/csharp/SwaggerClient/src/IO.Swagger/Model/ArrayTest.cs @@ -108,18 +108,18 @@ namespace IO.Swagger.Model return ( this.ArrayOfString == input.ArrayOfString || - (this.ArrayOfString != null && - this.ArrayOfString.SequenceEqual(input.ArrayOfString)) + this.ArrayOfString != null && + this.ArrayOfString.SequenceEqual(input.ArrayOfString) ) && ( this.ArrayArrayOfInteger == input.ArrayArrayOfInteger || - (this.ArrayArrayOfInteger != null && - this.ArrayArrayOfInteger.SequenceEqual(input.ArrayArrayOfInteger)) + this.ArrayArrayOfInteger != null && + this.ArrayArrayOfInteger.SequenceEqual(input.ArrayArrayOfInteger) ) && ( this.ArrayArrayOfModel == input.ArrayArrayOfModel || - (this.ArrayArrayOfModel != null && - this.ArrayArrayOfModel.SequenceEqual(input.ArrayArrayOfModel)) + this.ArrayArrayOfModel != null && + this.ArrayArrayOfModel.SequenceEqual(input.ArrayArrayOfModel) ); } diff --git a/samples/client/petstore/csharp/SwaggerClient/src/IO.Swagger/Model/Cat.cs b/samples/client/petstore/csharp/SwaggerClient/src/IO.Swagger/Model/Cat.cs index cdc9f2a46f5..b012af5de70 100644 --- a/samples/client/petstore/csharp/SwaggerClient/src/IO.Swagger/Model/Cat.cs +++ b/samples/client/petstore/csharp/SwaggerClient/src/IO.Swagger/Model/Cat.cs @@ -38,44 +38,12 @@ namespace IO.Swagger.Model /// /// Initializes a new instance of the class. /// - /// ClassName (required). - /// Color (default to "red"). /// Declawed. - public Cat(string ClassName = default(string), string Color = "red", bool? Declawed = default(bool?)) + public Cat(bool? Declawed = default(bool?), string ClassName = "Cat", string Color = "red") : base(ClassName, Color) { - // to ensure "ClassName" is required (not null) - if (ClassName == null) - { - throw new InvalidDataException("ClassName is a required property for Cat and cannot be null"); - } - else - { - this.ClassName = ClassName; - } - // use default value if no "Color" provided - if (Color == null) - { - this.Color = "red"; - } - else - { - this.Color = Color; - } this.Declawed = Declawed; } - /// - /// Gets or Sets ClassName - /// - [DataMember(Name="className", EmitDefaultValue=false)] - public string ClassName { get; set; } - - /// - /// Gets or Sets Color - /// - [DataMember(Name="color", EmitDefaultValue=false)] - public string Color { get; set; } - /// /// Gets or Sets Declawed /// @@ -90,8 +58,7 @@ namespace IO.Swagger.Model { var sb = new StringBuilder(); sb.Append("class Cat {\n"); - sb.Append(" ClassName: ").Append(ClassName).Append("\n"); - sb.Append(" Color: ").Append(Color).Append("\n"); + sb.Append(" ").Append(base.ToString().Replace("\n", "\n ")).Append("\n"); sb.Append(" Declawed: ").Append(Declawed).Append("\n"); sb.Append("}\n"); return sb.ToString(); @@ -101,7 +68,7 @@ namespace IO.Swagger.Model /// Returns the JSON string presentation of the object /// /// JSON string presentation of the object - public new string ToJson() + public override string ToJson() { return JsonConvert.SerializeObject(this, Formatting.Indented); } @@ -126,17 +93,7 @@ namespace IO.Swagger.Model if (input == null) return false; - return - ( - this.ClassName == input.ClassName || - (this.ClassName != null && - this.ClassName.Equals(input.ClassName)) - ) && - ( - this.Color == input.Color || - (this.Color != null && - this.Color.Equals(input.Color)) - ) && + return base.Equals(input) && ( this.Declawed == input.Declawed || (this.Declawed != null && @@ -152,11 +109,7 @@ namespace IO.Swagger.Model { unchecked // Overflow is fine, just wrap { - int hashCode = 41; - if (this.ClassName != null) - hashCode = hashCode * 59 + this.ClassName.GetHashCode(); - if (this.Color != null) - hashCode = hashCode * 59 + this.Color.GetHashCode(); + int hashCode = base.GetHashCode(); if (this.Declawed != null) hashCode = hashCode * 59 + this.Declawed.GetHashCode(); return hashCode; @@ -170,6 +123,7 @@ namespace IO.Swagger.Model /// Validation Result IEnumerable IValidatableObject.Validate(ValidationContext validationContext) { + foreach(var x in BaseValidate(validationContext)) yield return x; yield break; } } diff --git a/samples/client/petstore/csharp/SwaggerClient/src/IO.Swagger/Model/Dog.cs b/samples/client/petstore/csharp/SwaggerClient/src/IO.Swagger/Model/Dog.cs index 63196c32d05..f92b01a5bfb 100644 --- a/samples/client/petstore/csharp/SwaggerClient/src/IO.Swagger/Model/Dog.cs +++ b/samples/client/petstore/csharp/SwaggerClient/src/IO.Swagger/Model/Dog.cs @@ -38,44 +38,12 @@ namespace IO.Swagger.Model /// /// Initializes a new instance of the class. /// - /// ClassName (required). - /// Color (default to "red"). /// Breed. - public Dog(string ClassName = default(string), string Color = "red", string Breed = default(string)) + public Dog(string Breed = default(string), string ClassName = "Dog", string Color = "red") : base(ClassName, Color) { - // to ensure "ClassName" is required (not null) - if (ClassName == null) - { - throw new InvalidDataException("ClassName is a required property for Dog and cannot be null"); - } - else - { - this.ClassName = ClassName; - } - // use default value if no "Color" provided - if (Color == null) - { - this.Color = "red"; - } - else - { - this.Color = Color; - } this.Breed = Breed; } - /// - /// Gets or Sets ClassName - /// - [DataMember(Name="className", EmitDefaultValue=false)] - public string ClassName { get; set; } - - /// - /// Gets or Sets Color - /// - [DataMember(Name="color", EmitDefaultValue=false)] - public string Color { get; set; } - /// /// Gets or Sets Breed /// @@ -90,8 +58,7 @@ namespace IO.Swagger.Model { var sb = new StringBuilder(); sb.Append("class Dog {\n"); - sb.Append(" ClassName: ").Append(ClassName).Append("\n"); - sb.Append(" Color: ").Append(Color).Append("\n"); + sb.Append(" ").Append(base.ToString().Replace("\n", "\n ")).Append("\n"); sb.Append(" Breed: ").Append(Breed).Append("\n"); sb.Append("}\n"); return sb.ToString(); @@ -101,7 +68,7 @@ namespace IO.Swagger.Model /// Returns the JSON string presentation of the object /// /// JSON string presentation of the object - public new string ToJson() + public override string ToJson() { return JsonConvert.SerializeObject(this, Formatting.Indented); } @@ -126,17 +93,7 @@ namespace IO.Swagger.Model if (input == null) return false; - return - ( - this.ClassName == input.ClassName || - (this.ClassName != null && - this.ClassName.Equals(input.ClassName)) - ) && - ( - this.Color == input.Color || - (this.Color != null && - this.Color.Equals(input.Color)) - ) && + return base.Equals(input) && ( this.Breed == input.Breed || (this.Breed != null && @@ -152,11 +109,7 @@ namespace IO.Swagger.Model { unchecked // Overflow is fine, just wrap { - int hashCode = 41; - if (this.ClassName != null) - hashCode = hashCode * 59 + this.ClassName.GetHashCode(); - if (this.Color != null) - hashCode = hashCode * 59 + this.Color.GetHashCode(); + int hashCode = base.GetHashCode(); if (this.Breed != null) hashCode = hashCode * 59 + this.Breed.GetHashCode(); return hashCode; @@ -170,6 +123,7 @@ namespace IO.Swagger.Model /// Validation Result IEnumerable IValidatableObject.Validate(ValidationContext validationContext) { + foreach(var x in BaseValidate(validationContext)) yield return x; yield break; } } diff --git a/samples/client/petstore/csharp/SwaggerClient/src/IO.Swagger/Model/EnumArrays.cs b/samples/client/petstore/csharp/SwaggerClient/src/IO.Swagger/Model/EnumArrays.cs index 451c53fada6..64f705748f2 100644 --- a/samples/client/petstore/csharp/SwaggerClient/src/IO.Swagger/Model/EnumArrays.cs +++ b/samples/client/petstore/csharp/SwaggerClient/src/IO.Swagger/Model/EnumArrays.cs @@ -145,8 +145,8 @@ namespace IO.Swagger.Model ) && ( this.ArrayEnum == input.ArrayEnum || - (this.ArrayEnum != null && - this.ArrayEnum.SequenceEqual(input.ArrayEnum)) + this.ArrayEnum != null && + this.ArrayEnum.SequenceEqual(input.ArrayEnum) ); } diff --git a/samples/client/petstore/csharp/SwaggerClient/src/IO.Swagger/Model/MapTest.cs b/samples/client/petstore/csharp/SwaggerClient/src/IO.Swagger/Model/MapTest.cs index e0a68146d83..d5fe36c4151 100644 --- a/samples/client/petstore/csharp/SwaggerClient/src/IO.Swagger/Model/MapTest.cs +++ b/samples/client/petstore/csharp/SwaggerClient/src/IO.Swagger/Model/MapTest.cs @@ -120,13 +120,13 @@ namespace IO.Swagger.Model return ( this.MapMapOfString == input.MapMapOfString || - (this.MapMapOfString != null && - this.MapMapOfString.SequenceEqual(input.MapMapOfString)) + this.MapMapOfString != null && + this.MapMapOfString.SequenceEqual(input.MapMapOfString) ) && ( this.MapOfEnumString == input.MapOfEnumString || - (this.MapOfEnumString != null && - this.MapOfEnumString.SequenceEqual(input.MapOfEnumString)) + this.MapOfEnumString != null && + this.MapOfEnumString.SequenceEqual(input.MapOfEnumString) ); } diff --git a/samples/client/petstore/csharp/SwaggerClient/src/IO.Swagger/Model/MixedPropertiesAndAdditionalPropertiesClass.cs b/samples/client/petstore/csharp/SwaggerClient/src/IO.Swagger/Model/MixedPropertiesAndAdditionalPropertiesClass.cs index 8f17c8dd977..fb0a3998053 100644 --- a/samples/client/petstore/csharp/SwaggerClient/src/IO.Swagger/Model/MixedPropertiesAndAdditionalPropertiesClass.cs +++ b/samples/client/petstore/csharp/SwaggerClient/src/IO.Swagger/Model/MixedPropertiesAndAdditionalPropertiesClass.cs @@ -118,8 +118,8 @@ namespace IO.Swagger.Model ) && ( this.Map == input.Map || - (this.Map != null && - this.Map.SequenceEqual(input.Map)) + this.Map != null && + this.Map.SequenceEqual(input.Map) ); } diff --git a/samples/client/petstore/csharp/SwaggerClient/src/IO.Swagger/Model/Pet.cs b/samples/client/petstore/csharp/SwaggerClient/src/IO.Swagger/Model/Pet.cs index 4e3211a1654..fa39a5da19c 100644 --- a/samples/client/petstore/csharp/SwaggerClient/src/IO.Swagger/Model/Pet.cs +++ b/samples/client/petstore/csharp/SwaggerClient/src/IO.Swagger/Model/Pet.cs @@ -199,13 +199,13 @@ namespace IO.Swagger.Model ) && ( this.PhotoUrls == input.PhotoUrls || - (this.PhotoUrls != null && - this.PhotoUrls.SequenceEqual(input.PhotoUrls)) + this.PhotoUrls != null && + this.PhotoUrls.SequenceEqual(input.PhotoUrls) ) && ( this.Tags == input.Tags || - (this.Tags != null && - this.Tags.SequenceEqual(input.Tags)) + this.Tags != null && + this.Tags.SequenceEqual(input.Tags) ) && ( this.Status == input.Status || diff --git a/samples/client/petstore/csharp/SwaggerClientNetCoreProject/IO.Swagger.sln b/samples/client/petstore/csharp/SwaggerClientNetCoreProject/IO.Swagger.sln index b0a663d7650..ad0826e1f1e 100644 --- a/samples/client/petstore/csharp/SwaggerClientNetCoreProject/IO.Swagger.sln +++ b/samples/client/petstore/csharp/SwaggerClientNetCoreProject/IO.Swagger.sln @@ -5,21 +5,21 @@ MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "IO.Swagger", "src\IO.Swagger\IO.Swagger.csproj", "{67035b31-f8e5-41a4-9673-954035084f7d}" EndProject Global -GlobalSection(SolutionConfigurationPlatforms) = preSolution -Debug|Any CPU = Debug|Any CPU -Release|Any CPU = Release|Any CPU -EndGlobalSection -GlobalSection(ProjectConfigurationPlatforms) = postSolution -{67035b31-f8e5-41a4-9673-954035084f7d}.Debug|Any CPU.ActiveCfg = Debug|Any CPU -{67035b31-f8e5-41a4-9673-954035084f7d}.Debug|Any CPU.Build.0 = Debug|Any CPU -{67035b31-f8e5-41a4-9673-954035084f7d}.Release|Any CPU.ActiveCfg = Release|Any CPU -{67035b31-f8e5-41a4-9673-954035084f7d}.Release|Any CPU.Build.0 = Release|Any CPU -{19F1DEBC-DE5E-4517-8062-F000CD499087}.Debug|Any CPU.ActiveCfg = Debug|Any CPU -{19F1DEBC-DE5E-4517-8062-F000CD499087}.Debug|Any CPU.Build.0 = Debug|Any CPU -{19F1DEBC-DE5E-4517-8062-F000CD499087}.Release|Any CPU.ActiveCfg = Release|Any CPU -{19F1DEBC-DE5E-4517-8062-F000CD499087}.Release|Any CPU.Build.0 = Release|Any CPU -EndGlobalSection -GlobalSection(SolutionProperties) = preSolution -HideSolutionNode = FALSE -EndGlobalSection + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {67035b31-f8e5-41a4-9673-954035084f7d}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {67035b31-f8e5-41a4-9673-954035084f7d}.Debug|Any CPU.Build.0 = Debug|Any CPU + {67035b31-f8e5-41a4-9673-954035084f7d}.Release|Any CPU.ActiveCfg = Release|Any CPU + {67035b31-f8e5-41a4-9673-954035084f7d}.Release|Any CPU.Build.0 = Release|Any CPU + {19F1DEBC-DE5E-4517-8062-F000CD499087}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {19F1DEBC-DE5E-4517-8062-F000CD499087}.Debug|Any CPU.Build.0 = Debug|Any CPU + {19F1DEBC-DE5E-4517-8062-F000CD499087}.Release|Any CPU.ActiveCfg = Release|Any CPU + {19F1DEBC-DE5E-4517-8062-F000CD499087}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection EndGlobal \ No newline at end of file diff --git a/samples/client/petstore/csharp/SwaggerClientNetCoreProject/src/IO.Swagger/Client/JsonSubTypes.cs b/samples/client/petstore/csharp/SwaggerClientNetCoreProject/src/IO.Swagger/Client/JsonSubTypes.cs new file mode 100644 index 00000000000..3a6da091b78 --- /dev/null +++ b/samples/client/petstore/csharp/SwaggerClientNetCoreProject/src/IO.Swagger/Client/JsonSubTypes.cs @@ -0,0 +1,272 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; + +namespace JsonSubTypes +{ + // Copied from project https://github.com/manuc66/JsonSubTypes + // https://raw.githubusercontent.com/manuc66/JsonSubTypes/07403192ea3f4959f6d42f5966ac56ceb0d6095b/JsonSubTypes/JsonSubtypes.cs + + public class JsonSubtypes : JsonConverter + { + [AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface, AllowMultiple = true)] + public class KnownSubTypeAttribute : Attribute + { + public Type SubType { get; private set; } + public object AssociatedValue { get; private set; } + + public KnownSubTypeAttribute(Type subType, object associatedValue) + { + SubType = subType; + AssociatedValue = associatedValue; + } + } + [AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface, AllowMultiple = true)] + public class KnownSubTypeWithPropertyAttribute : Attribute + { + public Type SubType { get; private set; } + public string PropertyName { get; private set; } + + public KnownSubTypeWithPropertyAttribute(Type subType, string propertyName) + { + SubType = subType; + PropertyName = propertyName; + } + } + + private readonly string _typeMappingPropertyName; + + private bool _isInsideRead; + private JsonReader _reader; + + public override bool CanRead + { + get + { + if (!_isInsideRead) + return true; + + return !string.IsNullOrEmpty(_reader.Path); + } + } + + public sealed override bool CanWrite + { + get { return false; } + } + + public JsonSubtypes() + { + } + + public JsonSubtypes(string typeMappingPropertyName) + { + _typeMappingPropertyName = typeMappingPropertyName; + } + + public override bool CanConvert(Type objectType) + { + return _typeMappingPropertyName != null; + } + + public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) + { + throw new NotImplementedException(); + } + + public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) + { + if (reader.TokenType == JsonToken.Comment) + reader.Read(); + + switch (reader.TokenType) + { + case JsonToken.Null: + return null; + case JsonToken.StartArray: + return ReadArray(reader, objectType, serializer); + case JsonToken.StartObject: + return ReadObject(reader, objectType, serializer); + default: + throw new Exception("Array: Unrecognized token: " + reader.TokenType); + } + } + + private IList ReadArray(JsonReader reader, Type targetType, JsonSerializer serializer) + { + var elementType = GetElementType(targetType); + + var list = CreateCompatibleList(targetType, elementType); + + while (reader.TokenType != JsonToken.EndArray && reader.Read()) + { + switch (reader.TokenType) + { + case JsonToken.Null: + list.Add(reader.Value); + break; + case JsonToken.Comment: + break; + case JsonToken.StartObject: + list.Add(ReadObject(reader, elementType, serializer)); + break; + case JsonToken.EndArray: + break; + default: + throw new Exception("Array: Unrecognized token: " + reader.TokenType); + } + } + if (targetType.IsArray) + { + var array = Array.CreateInstance(targetType.GetElementType(), list.Count); + list.CopyTo(array, 0); + list = array; + } + return list; + } + + private static IList CreateCompatibleList(Type targetContainerType, Type elementType) + { + IList list; + if (targetContainerType.IsArray || targetContainerType.GetTypeInfo().IsAbstract) + { + list = (IList)Activator.CreateInstance(typeof(List<>).MakeGenericType(elementType)); + } + else + { + list = (IList)Activator.CreateInstance(targetContainerType); + } + return list; + } + + private static Type GetElementType(Type arrayOrGenericContainer) + { + Type elementType; + if (arrayOrGenericContainer.IsArray) + { + elementType = arrayOrGenericContainer.GetElementType(); + } + else + { + elementType = arrayOrGenericContainer.GenericTypeArguments[0]; + } + return elementType; + } + + private object ReadObject(JsonReader reader, Type objectType, JsonSerializer serializer) + { + var jObject = JObject.Load(reader); + + var targetType = GetType(jObject, objectType) ?? objectType; + + return _ReadJson(CreateAnotherReader(jObject, reader), targetType, null, serializer); + } + + private static JsonReader CreateAnotherReader(JObject jObject, JsonReader reader) + { + var jObjectReader = jObject.CreateReader(); + jObjectReader.Culture = reader.Culture; + jObjectReader.CloseInput = reader.CloseInput; + jObjectReader.SupportMultipleContent = reader.SupportMultipleContent; + jObjectReader.DateTimeZoneHandling = reader.DateTimeZoneHandling; + jObjectReader.FloatParseHandling = reader.FloatParseHandling; + jObjectReader.DateFormatString = reader.DateFormatString; + jObjectReader.DateParseHandling = reader.DateParseHandling; + return jObjectReader; + } + + public Type GetType(JObject jObject, Type parentType) + { + if (_typeMappingPropertyName == null) + { + return GetTypeByPropertyPresence(jObject, parentType); + } + return GetTypeFromDiscriminatorValue(jObject, parentType); + } + + private static Type GetTypeByPropertyPresence(JObject jObject, Type parentType) + { + foreach (var type in parentType.GetTypeInfo().GetCustomAttributes()) + { + JToken ignore; + if (jObject.TryGetValue(type.PropertyName, out ignore)) + { + return type.SubType; + } + } + return null; + } + + private Type GetTypeFromDiscriminatorValue(JObject jObject, Type parentType) + { + JToken jToken; + if (!jObject.TryGetValue(_typeMappingPropertyName, out jToken)) return null; + + var discriminatorValue = jToken.ToObject(); + if (discriminatorValue == null) return null; + + var typeMapping = GetSubTypeMapping(parentType); + if (typeMapping.Any()) + { + return GetTypeFromMapping(typeMapping, discriminatorValue); + } + return GetTypeByName(discriminatorValue as string, parentType); + } + + private static Type GetTypeByName(string typeName, Type parentType) + { + if (typeName == null) + return null; + + var insideAssembly = parentType.GetTypeInfo().Assembly; + + var typeByName = insideAssembly.GetType(typeName); + if (typeByName == null) + { + var searchLocation = parentType.FullName.Substring(0, parentType.FullName.Length - parentType.Name.Length); + typeByName = insideAssembly.GetType(searchLocation + typeName, false, true); + } + return typeByName; + } + + private static Type GetTypeFromMapping(IReadOnlyDictionary typeMapping, object discriminatorValue) + { + var targetlookupValueType = typeMapping.First().Key.GetType(); + var lookupValue = ConvertJsonValueToType(discriminatorValue, targetlookupValueType); + + Type targetType; + return typeMapping.TryGetValue(lookupValue, out targetType) ? targetType : null; + } + + private static Dictionary GetSubTypeMapping(Type type) + { + return type.GetTypeInfo().GetCustomAttributes().ToDictionary(x => x.AssociatedValue, x => x.SubType); + } + + private static object ConvertJsonValueToType(object objectType, Type targetlookupValueType) + { + if (targetlookupValueType.GetTypeInfo().IsEnum) + return Enum.ToObject(targetlookupValueType, objectType); + + return Convert.ChangeType(objectType, targetlookupValueType); + } + + protected object _ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) + { + _reader = reader; + _isInsideRead = true; + try + { + return serializer.Deserialize(reader, objectType); + } + finally + { + _isInsideRead = false; + } + } + } +} diff --git a/samples/client/petstore/csharp/SwaggerClientNetCoreProject/src/IO.Swagger/Model/Animal.cs b/samples/client/petstore/csharp/SwaggerClientNetCoreProject/src/IO.Swagger/Model/Animal.cs index e4ae9421f2f..e122ef49f46 100644 --- a/samples/client/petstore/csharp/SwaggerClientNetCoreProject/src/IO.Swagger/Model/Animal.cs +++ b/samples/client/petstore/csharp/SwaggerClientNetCoreProject/src/IO.Swagger/Model/Animal.cs @@ -18,6 +18,7 @@ using System.Collections.ObjectModel; using System.Runtime.Serialization; using Newtonsoft.Json; using Newtonsoft.Json.Converters; +using JsonSubTypes; using SwaggerDateConverter = IO.Swagger.Client.SwaggerDateConverter; namespace IO.Swagger.Model @@ -26,6 +27,9 @@ namespace IO.Swagger.Model /// Animal /// [DataContract] + [JsonConverter(typeof(JsonSubtypes), "className")] + [JsonSubtypes.KnownSubType(typeof(Dog), "Dog")] + [JsonSubtypes.KnownSubType(typeof(Cat), "Cat")] public partial class Animal : IEquatable { /// @@ -90,7 +94,7 @@ namespace IO.Swagger.Model /// Returns the JSON string presentation of the object /// /// JSON string presentation of the object - public string ToJson() + public virtual string ToJson() { return JsonConvert.SerializeObject(this, Formatting.Indented); } diff --git a/samples/client/petstore/csharp/SwaggerClientNetCoreProject/src/IO.Swagger/Model/AnimalFarm.cs b/samples/client/petstore/csharp/SwaggerClientNetCoreProject/src/IO.Swagger/Model/AnimalFarm.cs index d5346938104..786c6005a98 100644 --- a/samples/client/petstore/csharp/SwaggerClientNetCoreProject/src/IO.Swagger/Model/AnimalFarm.cs +++ b/samples/client/petstore/csharp/SwaggerClientNetCoreProject/src/IO.Swagger/Model/AnimalFarm.cs @@ -32,7 +32,7 @@ namespace IO.Swagger.Model /// Initializes a new instance of the class. /// [JsonConstructorAttribute] - public AnimalFarm() + public AnimalFarm() : base() { } @@ -44,6 +44,7 @@ namespace IO.Swagger.Model { var sb = new StringBuilder(); sb.Append("class AnimalFarm {\n"); + sb.Append(" ").Append(base.ToString().Replace("\n", "\n ")).Append("\n"); sb.Append("}\n"); return sb.ToString(); } @@ -52,7 +53,7 @@ namespace IO.Swagger.Model /// Returns the JSON string presentation of the object /// /// JSON string presentation of the object - public new string ToJson() + public string ToJson() { return JsonConvert.SerializeObject(this, Formatting.Indented); } @@ -79,7 +80,7 @@ namespace IO.Swagger.Model if (other == null) return false; - return false; + return base.Equals(other); } /// @@ -91,7 +92,7 @@ namespace IO.Swagger.Model // credit: http://stackoverflow.com/a/263416/677735 unchecked // Overflow is fine, just wrap { - int hash = 41; + int hash = base.GetHashCode(); // Suitable nullity checks etc, of course :) return hash; } diff --git a/samples/client/petstore/csharp/SwaggerClientNetCoreProject/src/IO.Swagger/Model/Cat.cs b/samples/client/petstore/csharp/SwaggerClientNetCoreProject/src/IO.Swagger/Model/Cat.cs index 027b7eb2bf9..c0f502292f8 100644 --- a/samples/client/petstore/csharp/SwaggerClientNetCoreProject/src/IO.Swagger/Model/Cat.cs +++ b/samples/client/petstore/csharp/SwaggerClientNetCoreProject/src/IO.Swagger/Model/Cat.cs @@ -36,44 +36,12 @@ namespace IO.Swagger.Model /// /// Initializes a new instance of the class. /// - /// ClassName (required). - /// Color (default to "red"). /// Declawed. - public Cat(string ClassName = default(string), string Color = "red", bool? Declawed = default(bool?)) + public Cat(bool? Declawed = default(bool?), string ClassName = "Cat", string Color = "red") : base(ClassName, Color) { - // to ensure "ClassName" is required (not null) - if (ClassName == null) - { - throw new InvalidDataException("ClassName is a required property for Cat and cannot be null"); - } - else - { - this.ClassName = ClassName; - } - // use default value if no "Color" provided - if (Color == null) - { - this.Color = "red"; - } - else - { - this.Color = Color; - } this.Declawed = Declawed; } - /// - /// Gets or Sets ClassName - /// - [DataMember(Name="className", EmitDefaultValue=false)] - public string ClassName { get; set; } - - /// - /// Gets or Sets Color - /// - [DataMember(Name="color", EmitDefaultValue=false)] - public string Color { get; set; } - /// /// Gets or Sets Declawed /// @@ -88,8 +56,7 @@ namespace IO.Swagger.Model { var sb = new StringBuilder(); sb.Append("class Cat {\n"); - sb.Append(" ClassName: ").Append(ClassName).Append("\n"); - sb.Append(" Color: ").Append(Color).Append("\n"); + sb.Append(" ").Append(base.ToString().Replace("\n", "\n ")).Append("\n"); sb.Append(" Declawed: ").Append(Declawed).Append("\n"); sb.Append("}\n"); return sb.ToString(); @@ -99,7 +66,7 @@ namespace IO.Swagger.Model /// Returns the JSON string presentation of the object /// /// JSON string presentation of the object - public new string ToJson() + public override string ToJson() { return JsonConvert.SerializeObject(this, Formatting.Indented); } @@ -126,17 +93,7 @@ namespace IO.Swagger.Model if (other == null) return false; - return - ( - this.ClassName == other.ClassName || - this.ClassName != null && - this.ClassName.Equals(other.ClassName) - ) && - ( - this.Color == other.Color || - this.Color != null && - this.Color.Equals(other.Color) - ) && + return base.Equals(other) && ( this.Declawed == other.Declawed || this.Declawed != null && @@ -153,12 +110,8 @@ namespace IO.Swagger.Model // credit: http://stackoverflow.com/a/263416/677735 unchecked // Overflow is fine, just wrap { - int hash = 41; + int hash = base.GetHashCode(); // Suitable nullity checks etc, of course :) - if (this.ClassName != null) - hash = hash * 59 + this.ClassName.GetHashCode(); - if (this.Color != null) - hash = hash * 59 + this.Color.GetHashCode(); if (this.Declawed != null) hash = hash * 59 + this.Declawed.GetHashCode(); return hash; diff --git a/samples/client/petstore/csharp/SwaggerClientNetCoreProject/src/IO.Swagger/Model/Dog.cs b/samples/client/petstore/csharp/SwaggerClientNetCoreProject/src/IO.Swagger/Model/Dog.cs index 092fdc74b0e..67eae6ae6ea 100644 --- a/samples/client/petstore/csharp/SwaggerClientNetCoreProject/src/IO.Swagger/Model/Dog.cs +++ b/samples/client/petstore/csharp/SwaggerClientNetCoreProject/src/IO.Swagger/Model/Dog.cs @@ -36,44 +36,12 @@ namespace IO.Swagger.Model /// /// Initializes a new instance of the class. /// - /// ClassName (required). - /// Color (default to "red"). /// Breed. - public Dog(string ClassName = default(string), string Color = "red", string Breed = default(string)) + public Dog(string Breed = default(string), string ClassName = "Dog", string Color = "red") : base(ClassName, Color) { - // to ensure "ClassName" is required (not null) - if (ClassName == null) - { - throw new InvalidDataException("ClassName is a required property for Dog and cannot be null"); - } - else - { - this.ClassName = ClassName; - } - // use default value if no "Color" provided - if (Color == null) - { - this.Color = "red"; - } - else - { - this.Color = Color; - } this.Breed = Breed; } - /// - /// Gets or Sets ClassName - /// - [DataMember(Name="className", EmitDefaultValue=false)] - public string ClassName { get; set; } - - /// - /// Gets or Sets Color - /// - [DataMember(Name="color", EmitDefaultValue=false)] - public string Color { get; set; } - /// /// Gets or Sets Breed /// @@ -88,8 +56,7 @@ namespace IO.Swagger.Model { var sb = new StringBuilder(); sb.Append("class Dog {\n"); - sb.Append(" ClassName: ").Append(ClassName).Append("\n"); - sb.Append(" Color: ").Append(Color).Append("\n"); + sb.Append(" ").Append(base.ToString().Replace("\n", "\n ")).Append("\n"); sb.Append(" Breed: ").Append(Breed).Append("\n"); sb.Append("}\n"); return sb.ToString(); @@ -99,7 +66,7 @@ namespace IO.Swagger.Model /// Returns the JSON string presentation of the object /// /// JSON string presentation of the object - public new string ToJson() + public override string ToJson() { return JsonConvert.SerializeObject(this, Formatting.Indented); } @@ -126,17 +93,7 @@ namespace IO.Swagger.Model if (other == null) return false; - return - ( - this.ClassName == other.ClassName || - this.ClassName != null && - this.ClassName.Equals(other.ClassName) - ) && - ( - this.Color == other.Color || - this.Color != null && - this.Color.Equals(other.Color) - ) && + return base.Equals(other) && ( this.Breed == other.Breed || this.Breed != null && @@ -153,12 +110,8 @@ namespace IO.Swagger.Model // credit: http://stackoverflow.com/a/263416/677735 unchecked // Overflow is fine, just wrap { - int hash = 41; + int hash = base.GetHashCode(); // Suitable nullity checks etc, of course :) - if (this.ClassName != null) - hash = hash * 59 + this.ClassName.GetHashCode(); - if (this.Color != null) - hash = hash * 59 + this.Color.GetHashCode(); if (this.Breed != null) hash = hash * 59 + this.Breed.GetHashCode(); return hash; diff --git a/samples/client/petstore/csharp/SwaggerClientNetStandard/IO.Swagger.sln b/samples/client/petstore/csharp/SwaggerClientNetStandard/IO.Swagger.sln index 32ab6d53fd3..9e432f73cbe 100644 --- a/samples/client/petstore/csharp/SwaggerClientNetStandard/IO.Swagger.sln +++ b/samples/client/petstore/csharp/SwaggerClientNetStandard/IO.Swagger.sln @@ -5,21 +5,21 @@ MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "IO.Swagger", "src\IO.Swagger\IO.Swagger.csproj", "{321C8C3F-0156-40C1-AE42-D59761FB9B6C}" EndProject Global -GlobalSection(SolutionConfigurationPlatforms) = preSolution -Debug|Any CPU = Debug|Any CPU -Release|Any CPU = Release|Any CPU -EndGlobalSection -GlobalSection(ProjectConfigurationPlatforms) = postSolution -{321C8C3F-0156-40C1-AE42-D59761FB9B6C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU -{321C8C3F-0156-40C1-AE42-D59761FB9B6C}.Debug|Any CPU.Build.0 = Debug|Any CPU -{321C8C3F-0156-40C1-AE42-D59761FB9B6C}.Release|Any CPU.ActiveCfg = Release|Any CPU -{321C8C3F-0156-40C1-AE42-D59761FB9B6C}.Release|Any CPU.Build.0 = Release|Any CPU -{19F1DEBC-DE5E-4517-8062-F000CD499087}.Debug|Any CPU.ActiveCfg = Debug|Any CPU -{19F1DEBC-DE5E-4517-8062-F000CD499087}.Debug|Any CPU.Build.0 = Debug|Any CPU -{19F1DEBC-DE5E-4517-8062-F000CD499087}.Release|Any CPU.ActiveCfg = Release|Any CPU -{19F1DEBC-DE5E-4517-8062-F000CD499087}.Release|Any CPU.Build.0 = Release|Any CPU -EndGlobalSection -GlobalSection(SolutionProperties) = preSolution -HideSolutionNode = FALSE -EndGlobalSection + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {321C8C3F-0156-40C1-AE42-D59761FB9B6C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {321C8C3F-0156-40C1-AE42-D59761FB9B6C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {321C8C3F-0156-40C1-AE42-D59761FB9B6C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {321C8C3F-0156-40C1-AE42-D59761FB9B6C}.Release|Any CPU.Build.0 = Release|Any CPU + {19F1DEBC-DE5E-4517-8062-F000CD499087}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {19F1DEBC-DE5E-4517-8062-F000CD499087}.Debug|Any CPU.Build.0 = Debug|Any CPU + {19F1DEBC-DE5E-4517-8062-F000CD499087}.Release|Any CPU.ActiveCfg = Release|Any CPU + {19F1DEBC-DE5E-4517-8062-F000CD499087}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection EndGlobal \ No newline at end of file diff --git a/samples/client/petstore/csharp/SwaggerClientNetStandard/src/IO.Swagger/Client/JsonSubTypes.cs b/samples/client/petstore/csharp/SwaggerClientNetStandard/src/IO.Swagger/Client/JsonSubTypes.cs new file mode 100644 index 00000000000..3a6da091b78 --- /dev/null +++ b/samples/client/petstore/csharp/SwaggerClientNetStandard/src/IO.Swagger/Client/JsonSubTypes.cs @@ -0,0 +1,272 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; + +namespace JsonSubTypes +{ + // Copied from project https://github.com/manuc66/JsonSubTypes + // https://raw.githubusercontent.com/manuc66/JsonSubTypes/07403192ea3f4959f6d42f5966ac56ceb0d6095b/JsonSubTypes/JsonSubtypes.cs + + public class JsonSubtypes : JsonConverter + { + [AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface, AllowMultiple = true)] + public class KnownSubTypeAttribute : Attribute + { + public Type SubType { get; private set; } + public object AssociatedValue { get; private set; } + + public KnownSubTypeAttribute(Type subType, object associatedValue) + { + SubType = subType; + AssociatedValue = associatedValue; + } + } + [AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface, AllowMultiple = true)] + public class KnownSubTypeWithPropertyAttribute : Attribute + { + public Type SubType { get; private set; } + public string PropertyName { get; private set; } + + public KnownSubTypeWithPropertyAttribute(Type subType, string propertyName) + { + SubType = subType; + PropertyName = propertyName; + } + } + + private readonly string _typeMappingPropertyName; + + private bool _isInsideRead; + private JsonReader _reader; + + public override bool CanRead + { + get + { + if (!_isInsideRead) + return true; + + return !string.IsNullOrEmpty(_reader.Path); + } + } + + public sealed override bool CanWrite + { + get { return false; } + } + + public JsonSubtypes() + { + } + + public JsonSubtypes(string typeMappingPropertyName) + { + _typeMappingPropertyName = typeMappingPropertyName; + } + + public override bool CanConvert(Type objectType) + { + return _typeMappingPropertyName != null; + } + + public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) + { + throw new NotImplementedException(); + } + + public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) + { + if (reader.TokenType == JsonToken.Comment) + reader.Read(); + + switch (reader.TokenType) + { + case JsonToken.Null: + return null; + case JsonToken.StartArray: + return ReadArray(reader, objectType, serializer); + case JsonToken.StartObject: + return ReadObject(reader, objectType, serializer); + default: + throw new Exception("Array: Unrecognized token: " + reader.TokenType); + } + } + + private IList ReadArray(JsonReader reader, Type targetType, JsonSerializer serializer) + { + var elementType = GetElementType(targetType); + + var list = CreateCompatibleList(targetType, elementType); + + while (reader.TokenType != JsonToken.EndArray && reader.Read()) + { + switch (reader.TokenType) + { + case JsonToken.Null: + list.Add(reader.Value); + break; + case JsonToken.Comment: + break; + case JsonToken.StartObject: + list.Add(ReadObject(reader, elementType, serializer)); + break; + case JsonToken.EndArray: + break; + default: + throw new Exception("Array: Unrecognized token: " + reader.TokenType); + } + } + if (targetType.IsArray) + { + var array = Array.CreateInstance(targetType.GetElementType(), list.Count); + list.CopyTo(array, 0); + list = array; + } + return list; + } + + private static IList CreateCompatibleList(Type targetContainerType, Type elementType) + { + IList list; + if (targetContainerType.IsArray || targetContainerType.GetTypeInfo().IsAbstract) + { + list = (IList)Activator.CreateInstance(typeof(List<>).MakeGenericType(elementType)); + } + else + { + list = (IList)Activator.CreateInstance(targetContainerType); + } + return list; + } + + private static Type GetElementType(Type arrayOrGenericContainer) + { + Type elementType; + if (arrayOrGenericContainer.IsArray) + { + elementType = arrayOrGenericContainer.GetElementType(); + } + else + { + elementType = arrayOrGenericContainer.GenericTypeArguments[0]; + } + return elementType; + } + + private object ReadObject(JsonReader reader, Type objectType, JsonSerializer serializer) + { + var jObject = JObject.Load(reader); + + var targetType = GetType(jObject, objectType) ?? objectType; + + return _ReadJson(CreateAnotherReader(jObject, reader), targetType, null, serializer); + } + + private static JsonReader CreateAnotherReader(JObject jObject, JsonReader reader) + { + var jObjectReader = jObject.CreateReader(); + jObjectReader.Culture = reader.Culture; + jObjectReader.CloseInput = reader.CloseInput; + jObjectReader.SupportMultipleContent = reader.SupportMultipleContent; + jObjectReader.DateTimeZoneHandling = reader.DateTimeZoneHandling; + jObjectReader.FloatParseHandling = reader.FloatParseHandling; + jObjectReader.DateFormatString = reader.DateFormatString; + jObjectReader.DateParseHandling = reader.DateParseHandling; + return jObjectReader; + } + + public Type GetType(JObject jObject, Type parentType) + { + if (_typeMappingPropertyName == null) + { + return GetTypeByPropertyPresence(jObject, parentType); + } + return GetTypeFromDiscriminatorValue(jObject, parentType); + } + + private static Type GetTypeByPropertyPresence(JObject jObject, Type parentType) + { + foreach (var type in parentType.GetTypeInfo().GetCustomAttributes()) + { + JToken ignore; + if (jObject.TryGetValue(type.PropertyName, out ignore)) + { + return type.SubType; + } + } + return null; + } + + private Type GetTypeFromDiscriminatorValue(JObject jObject, Type parentType) + { + JToken jToken; + if (!jObject.TryGetValue(_typeMappingPropertyName, out jToken)) return null; + + var discriminatorValue = jToken.ToObject(); + if (discriminatorValue == null) return null; + + var typeMapping = GetSubTypeMapping(parentType); + if (typeMapping.Any()) + { + return GetTypeFromMapping(typeMapping, discriminatorValue); + } + return GetTypeByName(discriminatorValue as string, parentType); + } + + private static Type GetTypeByName(string typeName, Type parentType) + { + if (typeName == null) + return null; + + var insideAssembly = parentType.GetTypeInfo().Assembly; + + var typeByName = insideAssembly.GetType(typeName); + if (typeByName == null) + { + var searchLocation = parentType.FullName.Substring(0, parentType.FullName.Length - parentType.Name.Length); + typeByName = insideAssembly.GetType(searchLocation + typeName, false, true); + } + return typeByName; + } + + private static Type GetTypeFromMapping(IReadOnlyDictionary typeMapping, object discriminatorValue) + { + var targetlookupValueType = typeMapping.First().Key.GetType(); + var lookupValue = ConvertJsonValueToType(discriminatorValue, targetlookupValueType); + + Type targetType; + return typeMapping.TryGetValue(lookupValue, out targetType) ? targetType : null; + } + + private static Dictionary GetSubTypeMapping(Type type) + { + return type.GetTypeInfo().GetCustomAttributes().ToDictionary(x => x.AssociatedValue, x => x.SubType); + } + + private static object ConvertJsonValueToType(object objectType, Type targetlookupValueType) + { + if (targetlookupValueType.GetTypeInfo().IsEnum) + return Enum.ToObject(targetlookupValueType, objectType); + + return Convert.ChangeType(objectType, targetlookupValueType); + } + + protected object _ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) + { + _reader = reader; + _isInsideRead = true; + try + { + return serializer.Deserialize(reader, objectType); + } + finally + { + _isInsideRead = false; + } + } + } +} diff --git a/samples/client/petstore/csharp/SwaggerClientNetStandard/src/IO.Swagger/Model/AdditionalPropertiesClass.cs b/samples/client/petstore/csharp/SwaggerClientNetStandard/src/IO.Swagger/Model/AdditionalPropertiesClass.cs index abbedd7b4a0..879bb7fcede 100644 --- a/samples/client/petstore/csharp/SwaggerClientNetStandard/src/IO.Swagger/Model/AdditionalPropertiesClass.cs +++ b/samples/client/petstore/csharp/SwaggerClientNetStandard/src/IO.Swagger/Model/AdditionalPropertiesClass.cs @@ -97,13 +97,13 @@ namespace IO.Swagger.Model return ( this.MapProperty == input.MapProperty || - (this.MapProperty != null && - this.MapProperty.SequenceEqual(input.MapProperty)) + this.MapProperty != null && + this.MapProperty.SequenceEqual(input.MapProperty) ) && ( this.MapOfMapProperty == input.MapOfMapProperty || - (this.MapOfMapProperty != null && - this.MapOfMapProperty.SequenceEqual(input.MapOfMapProperty)) + this.MapOfMapProperty != null && + this.MapOfMapProperty.SequenceEqual(input.MapOfMapProperty) ); } diff --git a/samples/client/petstore/csharp/SwaggerClientNetStandard/src/IO.Swagger/Model/Animal.cs b/samples/client/petstore/csharp/SwaggerClientNetStandard/src/IO.Swagger/Model/Animal.cs index 0f2c563bde1..b0b642e09ff 100644 --- a/samples/client/petstore/csharp/SwaggerClientNetStandard/src/IO.Swagger/Model/Animal.cs +++ b/samples/client/petstore/csharp/SwaggerClientNetStandard/src/IO.Swagger/Model/Animal.cs @@ -18,6 +18,7 @@ using System.Collections.ObjectModel; using System.Runtime.Serialization; using Newtonsoft.Json; using Newtonsoft.Json.Converters; +using JsonSubTypes; using SwaggerDateConverter = IO.Swagger.Client.SwaggerDateConverter; namespace IO.Swagger.Model @@ -26,6 +27,9 @@ namespace IO.Swagger.Model /// Animal /// [DataContract] + [JsonConverter(typeof(JsonSubtypes), "className")] + [JsonSubtypes.KnownSubType(typeof(Dog), "Dog")] + [JsonSubtypes.KnownSubType(typeof(Cat), "Cat")] public partial class Animal : IEquatable { /// @@ -90,7 +94,7 @@ namespace IO.Swagger.Model /// Returns the JSON string presentation of the object /// /// JSON string presentation of the object - public string ToJson() + public virtual string ToJson() { return JsonConvert.SerializeObject(this, Formatting.Indented); } diff --git a/samples/client/petstore/csharp/SwaggerClientNetStandard/src/IO.Swagger/Model/AnimalFarm.cs b/samples/client/petstore/csharp/SwaggerClientNetStandard/src/IO.Swagger/Model/AnimalFarm.cs index 6e85a1197d7..29b66e92d25 100644 --- a/samples/client/petstore/csharp/SwaggerClientNetStandard/src/IO.Swagger/Model/AnimalFarm.cs +++ b/samples/client/petstore/csharp/SwaggerClientNetStandard/src/IO.Swagger/Model/AnimalFarm.cs @@ -32,7 +32,7 @@ namespace IO.Swagger.Model /// Initializes a new instance of the class. /// [JsonConstructorAttribute] - public AnimalFarm() + public AnimalFarm() : base() { } @@ -44,6 +44,7 @@ namespace IO.Swagger.Model { var sb = new StringBuilder(); sb.Append("class AnimalFarm {\n"); + sb.Append(" ").Append(base.ToString().Replace("\n", "\n ")).Append("\n"); sb.Append("}\n"); return sb.ToString(); } @@ -52,7 +53,7 @@ namespace IO.Swagger.Model /// Returns the JSON string presentation of the object /// /// JSON string presentation of the object - public new string ToJson() + public string ToJson() { return JsonConvert.SerializeObject(this, Formatting.Indented); } @@ -77,7 +78,7 @@ namespace IO.Swagger.Model if (input == null) return false; - return false; + return base.Equals(input); } /// @@ -88,7 +89,7 @@ namespace IO.Swagger.Model { unchecked // Overflow is fine, just wrap { - int hashCode = 41; + int hashCode = base.GetHashCode(); return hashCode; } } diff --git a/samples/client/petstore/csharp/SwaggerClientNetStandard/src/IO.Swagger/Model/ArrayOfArrayOfNumberOnly.cs b/samples/client/petstore/csharp/SwaggerClientNetStandard/src/IO.Swagger/Model/ArrayOfArrayOfNumberOnly.cs index 1efbeb285c7..011c403f455 100644 --- a/samples/client/petstore/csharp/SwaggerClientNetStandard/src/IO.Swagger/Model/ArrayOfArrayOfNumberOnly.cs +++ b/samples/client/petstore/csharp/SwaggerClientNetStandard/src/IO.Swagger/Model/ArrayOfArrayOfNumberOnly.cs @@ -88,8 +88,8 @@ namespace IO.Swagger.Model return ( this.ArrayArrayNumber == input.ArrayArrayNumber || - (this.ArrayArrayNumber != null && - this.ArrayArrayNumber.SequenceEqual(input.ArrayArrayNumber)) + this.ArrayArrayNumber != null && + this.ArrayArrayNumber.SequenceEqual(input.ArrayArrayNumber) ); } diff --git a/samples/client/petstore/csharp/SwaggerClientNetStandard/src/IO.Swagger/Model/ArrayOfNumberOnly.cs b/samples/client/petstore/csharp/SwaggerClientNetStandard/src/IO.Swagger/Model/ArrayOfNumberOnly.cs index 9f648182311..fe3f3f2fa86 100644 --- a/samples/client/petstore/csharp/SwaggerClientNetStandard/src/IO.Swagger/Model/ArrayOfNumberOnly.cs +++ b/samples/client/petstore/csharp/SwaggerClientNetStandard/src/IO.Swagger/Model/ArrayOfNumberOnly.cs @@ -88,8 +88,8 @@ namespace IO.Swagger.Model return ( this.ArrayNumber == input.ArrayNumber || - (this.ArrayNumber != null && - this.ArrayNumber.SequenceEqual(input.ArrayNumber)) + this.ArrayNumber != null && + this.ArrayNumber.SequenceEqual(input.ArrayNumber) ); } diff --git a/samples/client/petstore/csharp/SwaggerClientNetStandard/src/IO.Swagger/Model/ArrayTest.cs b/samples/client/petstore/csharp/SwaggerClientNetStandard/src/IO.Swagger/Model/ArrayTest.cs index ddd1bc881f1..f1e32b23b9c 100644 --- a/samples/client/petstore/csharp/SwaggerClientNetStandard/src/IO.Swagger/Model/ArrayTest.cs +++ b/samples/client/petstore/csharp/SwaggerClientNetStandard/src/IO.Swagger/Model/ArrayTest.cs @@ -106,18 +106,18 @@ namespace IO.Swagger.Model return ( this.ArrayOfString == input.ArrayOfString || - (this.ArrayOfString != null && - this.ArrayOfString.SequenceEqual(input.ArrayOfString)) + this.ArrayOfString != null && + this.ArrayOfString.SequenceEqual(input.ArrayOfString) ) && ( this.ArrayArrayOfInteger == input.ArrayArrayOfInteger || - (this.ArrayArrayOfInteger != null && - this.ArrayArrayOfInteger.SequenceEqual(input.ArrayArrayOfInteger)) + this.ArrayArrayOfInteger != null && + this.ArrayArrayOfInteger.SequenceEqual(input.ArrayArrayOfInteger) ) && ( this.ArrayArrayOfModel == input.ArrayArrayOfModel || - (this.ArrayArrayOfModel != null && - this.ArrayArrayOfModel.SequenceEqual(input.ArrayArrayOfModel)) + this.ArrayArrayOfModel != null && + this.ArrayArrayOfModel.SequenceEqual(input.ArrayArrayOfModel) ); } diff --git a/samples/client/petstore/csharp/SwaggerClientNetStandard/src/IO.Swagger/Model/Cat.cs b/samples/client/petstore/csharp/SwaggerClientNetStandard/src/IO.Swagger/Model/Cat.cs index 0d308f2cdad..555746a83fe 100644 --- a/samples/client/petstore/csharp/SwaggerClientNetStandard/src/IO.Swagger/Model/Cat.cs +++ b/samples/client/petstore/csharp/SwaggerClientNetStandard/src/IO.Swagger/Model/Cat.cs @@ -36,44 +36,12 @@ namespace IO.Swagger.Model /// /// Initializes a new instance of the class. /// - /// ClassName (required). - /// Color (default to "red"). /// Declawed. - public Cat(string ClassName = default(string), string Color = "red", bool? Declawed = default(bool?)) + public Cat(bool? Declawed = default(bool?), string ClassName = "Cat", string Color = "red") : base(ClassName, Color) { - // to ensure "ClassName" is required (not null) - if (ClassName == null) - { - throw new InvalidDataException("ClassName is a required property for Cat and cannot be null"); - } - else - { - this.ClassName = ClassName; - } - // use default value if no "Color" provided - if (Color == null) - { - this.Color = "red"; - } - else - { - this.Color = Color; - } this.Declawed = Declawed; } - /// - /// Gets or Sets ClassName - /// - [DataMember(Name="className", EmitDefaultValue=false)] - public string ClassName { get; set; } - - /// - /// Gets or Sets Color - /// - [DataMember(Name="color", EmitDefaultValue=false)] - public string Color { get; set; } - /// /// Gets or Sets Declawed /// @@ -88,8 +56,7 @@ namespace IO.Swagger.Model { var sb = new StringBuilder(); sb.Append("class Cat {\n"); - sb.Append(" ClassName: ").Append(ClassName).Append("\n"); - sb.Append(" Color: ").Append(Color).Append("\n"); + sb.Append(" ").Append(base.ToString().Replace("\n", "\n ")).Append("\n"); sb.Append(" Declawed: ").Append(Declawed).Append("\n"); sb.Append("}\n"); return sb.ToString(); @@ -99,7 +66,7 @@ namespace IO.Swagger.Model /// Returns the JSON string presentation of the object /// /// JSON string presentation of the object - public new string ToJson() + public override string ToJson() { return JsonConvert.SerializeObject(this, Formatting.Indented); } @@ -124,17 +91,7 @@ namespace IO.Swagger.Model if (input == null) return false; - return - ( - this.ClassName == input.ClassName || - (this.ClassName != null && - this.ClassName.Equals(input.ClassName)) - ) && - ( - this.Color == input.Color || - (this.Color != null && - this.Color.Equals(input.Color)) - ) && + return base.Equals(input) && ( this.Declawed == input.Declawed || (this.Declawed != null && @@ -150,11 +107,7 @@ namespace IO.Swagger.Model { unchecked // Overflow is fine, just wrap { - int hashCode = 41; - if (this.ClassName != null) - hashCode = hashCode * 59 + this.ClassName.GetHashCode(); - if (this.Color != null) - hashCode = hashCode * 59 + this.Color.GetHashCode(); + int hashCode = base.GetHashCode(); if (this.Declawed != null) hashCode = hashCode * 59 + this.Declawed.GetHashCode(); return hashCode; diff --git a/samples/client/petstore/csharp/SwaggerClientNetStandard/src/IO.Swagger/Model/Dog.cs b/samples/client/petstore/csharp/SwaggerClientNetStandard/src/IO.Swagger/Model/Dog.cs index ae6f09d160f..672511560d0 100644 --- a/samples/client/petstore/csharp/SwaggerClientNetStandard/src/IO.Swagger/Model/Dog.cs +++ b/samples/client/petstore/csharp/SwaggerClientNetStandard/src/IO.Swagger/Model/Dog.cs @@ -36,44 +36,12 @@ namespace IO.Swagger.Model /// /// Initializes a new instance of the class. /// - /// ClassName (required). - /// Color (default to "red"). /// Breed. - public Dog(string ClassName = default(string), string Color = "red", string Breed = default(string)) + public Dog(string Breed = default(string), string ClassName = "Dog", string Color = "red") : base(ClassName, Color) { - // to ensure "ClassName" is required (not null) - if (ClassName == null) - { - throw new InvalidDataException("ClassName is a required property for Dog and cannot be null"); - } - else - { - this.ClassName = ClassName; - } - // use default value if no "Color" provided - if (Color == null) - { - this.Color = "red"; - } - else - { - this.Color = Color; - } this.Breed = Breed; } - /// - /// Gets or Sets ClassName - /// - [DataMember(Name="className", EmitDefaultValue=false)] - public string ClassName { get; set; } - - /// - /// Gets or Sets Color - /// - [DataMember(Name="color", EmitDefaultValue=false)] - public string Color { get; set; } - /// /// Gets or Sets Breed /// @@ -88,8 +56,7 @@ namespace IO.Swagger.Model { var sb = new StringBuilder(); sb.Append("class Dog {\n"); - sb.Append(" ClassName: ").Append(ClassName).Append("\n"); - sb.Append(" Color: ").Append(Color).Append("\n"); + sb.Append(" ").Append(base.ToString().Replace("\n", "\n ")).Append("\n"); sb.Append(" Breed: ").Append(Breed).Append("\n"); sb.Append("}\n"); return sb.ToString(); @@ -99,7 +66,7 @@ namespace IO.Swagger.Model /// Returns the JSON string presentation of the object /// /// JSON string presentation of the object - public new string ToJson() + public override string ToJson() { return JsonConvert.SerializeObject(this, Formatting.Indented); } @@ -124,17 +91,7 @@ namespace IO.Swagger.Model if (input == null) return false; - return - ( - this.ClassName == input.ClassName || - (this.ClassName != null && - this.ClassName.Equals(input.ClassName)) - ) && - ( - this.Color == input.Color || - (this.Color != null && - this.Color.Equals(input.Color)) - ) && + return base.Equals(input) && ( this.Breed == input.Breed || (this.Breed != null && @@ -150,11 +107,7 @@ namespace IO.Swagger.Model { unchecked // Overflow is fine, just wrap { - int hashCode = 41; - if (this.ClassName != null) - hashCode = hashCode * 59 + this.ClassName.GetHashCode(); - if (this.Color != null) - hashCode = hashCode * 59 + this.Color.GetHashCode(); + int hashCode = base.GetHashCode(); if (this.Breed != null) hashCode = hashCode * 59 + this.Breed.GetHashCode(); return hashCode; diff --git a/samples/client/petstore/csharp/SwaggerClientNetStandard/src/IO.Swagger/Model/EnumArrays.cs b/samples/client/petstore/csharp/SwaggerClientNetStandard/src/IO.Swagger/Model/EnumArrays.cs index 91c96bd77fc..28bbb15ea78 100644 --- a/samples/client/petstore/csharp/SwaggerClientNetStandard/src/IO.Swagger/Model/EnumArrays.cs +++ b/samples/client/petstore/csharp/SwaggerClientNetStandard/src/IO.Swagger/Model/EnumArrays.cs @@ -143,8 +143,8 @@ namespace IO.Swagger.Model ) && ( this.ArrayEnum == input.ArrayEnum || - (this.ArrayEnum != null && - this.ArrayEnum.SequenceEqual(input.ArrayEnum)) + this.ArrayEnum != null && + this.ArrayEnum.SequenceEqual(input.ArrayEnum) ); } diff --git a/samples/client/petstore/csharp/SwaggerClientNetStandard/src/IO.Swagger/Model/MapTest.cs b/samples/client/petstore/csharp/SwaggerClientNetStandard/src/IO.Swagger/Model/MapTest.cs index 35f5362abd8..42ee91a79cf 100644 --- a/samples/client/petstore/csharp/SwaggerClientNetStandard/src/IO.Swagger/Model/MapTest.cs +++ b/samples/client/petstore/csharp/SwaggerClientNetStandard/src/IO.Swagger/Model/MapTest.cs @@ -118,13 +118,13 @@ namespace IO.Swagger.Model return ( this.MapMapOfString == input.MapMapOfString || - (this.MapMapOfString != null && - this.MapMapOfString.SequenceEqual(input.MapMapOfString)) + this.MapMapOfString != null && + this.MapMapOfString.SequenceEqual(input.MapMapOfString) ) && ( this.MapOfEnumString == input.MapOfEnumString || - (this.MapOfEnumString != null && - this.MapOfEnumString.SequenceEqual(input.MapOfEnumString)) + this.MapOfEnumString != null && + this.MapOfEnumString.SequenceEqual(input.MapOfEnumString) ); } diff --git a/samples/client/petstore/csharp/SwaggerClientNetStandard/src/IO.Swagger/Model/MixedPropertiesAndAdditionalPropertiesClass.cs b/samples/client/petstore/csharp/SwaggerClientNetStandard/src/IO.Swagger/Model/MixedPropertiesAndAdditionalPropertiesClass.cs index a16e6b23501..3fa6f8d7d2f 100644 --- a/samples/client/petstore/csharp/SwaggerClientNetStandard/src/IO.Swagger/Model/MixedPropertiesAndAdditionalPropertiesClass.cs +++ b/samples/client/petstore/csharp/SwaggerClientNetStandard/src/IO.Swagger/Model/MixedPropertiesAndAdditionalPropertiesClass.cs @@ -116,8 +116,8 @@ namespace IO.Swagger.Model ) && ( this.Map == input.Map || - (this.Map != null && - this.Map.SequenceEqual(input.Map)) + this.Map != null && + this.Map.SequenceEqual(input.Map) ); } diff --git a/samples/client/petstore/csharp/SwaggerClientNetStandard/src/IO.Swagger/Model/Pet.cs b/samples/client/petstore/csharp/SwaggerClientNetStandard/src/IO.Swagger/Model/Pet.cs index 3e51a067ea2..ef434ebe581 100644 --- a/samples/client/petstore/csharp/SwaggerClientNetStandard/src/IO.Swagger/Model/Pet.cs +++ b/samples/client/petstore/csharp/SwaggerClientNetStandard/src/IO.Swagger/Model/Pet.cs @@ -197,13 +197,13 @@ namespace IO.Swagger.Model ) && ( this.PhotoUrls == input.PhotoUrls || - (this.PhotoUrls != null && - this.PhotoUrls.SequenceEqual(input.PhotoUrls)) + this.PhotoUrls != null && + this.PhotoUrls.SequenceEqual(input.PhotoUrls) ) && ( this.Tags == input.Tags || - (this.Tags != null && - this.Tags.SequenceEqual(input.Tags)) + this.Tags != null && + this.Tags.SequenceEqual(input.Tags) ) && ( this.Status == input.Status || diff --git a/samples/client/petstore/csharp/SwaggerClientWithPropertyChanged/IO.Swagger.sln b/samples/client/petstore/csharp/SwaggerClientWithPropertyChanged/IO.Swagger.sln index 4a35e02519c..9c0c36a33b8 100644 --- a/samples/client/petstore/csharp/SwaggerClientWithPropertyChanged/IO.Swagger.sln +++ b/samples/client/petstore/csharp/SwaggerClientWithPropertyChanged/IO.Swagger.sln @@ -7,21 +7,21 @@ EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "IO.Swagger.Test", "src\IO.Swagger.Test\IO.Swagger.Test.csproj", "{19F1DEBC-DE5E-4517-8062-F000CD499087}" EndProject Global -GlobalSection(SolutionConfigurationPlatforms) = preSolution -Debug|Any CPU = Debug|Any CPU -Release|Any CPU = Release|Any CPU -EndGlobalSection -GlobalSection(ProjectConfigurationPlatforms) = postSolution -{5CD900DE-8266-412F-A758-28E1F9C623D5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU -{5CD900DE-8266-412F-A758-28E1F9C623D5}.Debug|Any CPU.Build.0 = Debug|Any CPU -{5CD900DE-8266-412F-A758-28E1F9C623D5}.Release|Any CPU.ActiveCfg = Release|Any CPU -{5CD900DE-8266-412F-A758-28E1F9C623D5}.Release|Any CPU.Build.0 = Release|Any CPU -{19F1DEBC-DE5E-4517-8062-F000CD499087}.Debug|Any CPU.ActiveCfg = Debug|Any CPU -{19F1DEBC-DE5E-4517-8062-F000CD499087}.Debug|Any CPU.Build.0 = Debug|Any CPU -{19F1DEBC-DE5E-4517-8062-F000CD499087}.Release|Any CPU.ActiveCfg = Release|Any CPU -{19F1DEBC-DE5E-4517-8062-F000CD499087}.Release|Any CPU.Build.0 = Release|Any CPU -EndGlobalSection -GlobalSection(SolutionProperties) = preSolution -HideSolutionNode = FALSE -EndGlobalSection + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {5CD900DE-8266-412F-A758-28E1F9C623D5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5CD900DE-8266-412F-A758-28E1F9C623D5}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5CD900DE-8266-412F-A758-28E1F9C623D5}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5CD900DE-8266-412F-A758-28E1F9C623D5}.Release|Any CPU.Build.0 = Release|Any CPU + {19F1DEBC-DE5E-4517-8062-F000CD499087}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {19F1DEBC-DE5E-4517-8062-F000CD499087}.Debug|Any CPU.Build.0 = Debug|Any CPU + {19F1DEBC-DE5E-4517-8062-F000CD499087}.Release|Any CPU.ActiveCfg = Release|Any CPU + {19F1DEBC-DE5E-4517-8062-F000CD499087}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection EndGlobal \ No newline at end of file diff --git a/samples/client/petstore/csharp/SwaggerClientWithPropertyChanged/src/IO.Swagger.Test/Model/AnimalTests.cs b/samples/client/petstore/csharp/SwaggerClientWithPropertyChanged/src/IO.Swagger.Test/Model/AnimalTests.cs index 7f6b9a8b413..e877b597a37 100644 --- a/samples/client/petstore/csharp/SwaggerClientWithPropertyChanged/src/IO.Swagger.Test/Model/AnimalTests.cs +++ b/samples/client/petstore/csharp/SwaggerClientWithPropertyChanged/src/IO.Swagger.Test/Model/AnimalTests.cs @@ -31,6 +31,7 @@ using IO.Swagger.Api; using IO.Swagger.Model; using IO.Swagger.Client; using System.Reflection; +using Newtonsoft.Json; namespace IO.Swagger.Test { @@ -76,6 +77,25 @@ namespace IO.Swagger.Test //Assert.IsInstanceOfType (instance, "variable 'instance' is a Animal"); } + /// + /// Test deserialize a Dog from type Animal + /// + [Test] + public void DogDeserializeFromAnimalTest() + { + // TODO uncomment below to test deserialize a Dog from type Animal + //Assert.IsInstanceOf(JsonConvert.DeserializeObject(new Dog().ToJson())); + } + /// + /// Test deserialize a Cat from type Animal + /// + [Test] + public void CatDeserializeFromAnimalTest() + { + // TODO uncomment below to test deserialize a Cat from type Animal + //Assert.IsInstanceOf(JsonConvert.DeserializeObject(new Cat().ToJson())); + } + /// /// Test the property 'ClassName' /// diff --git a/samples/client/petstore/csharp/SwaggerClientWithPropertyChanged/src/IO.Swagger/Client/JsonSubTypes.cs b/samples/client/petstore/csharp/SwaggerClientWithPropertyChanged/src/IO.Swagger/Client/JsonSubTypes.cs new file mode 100644 index 00000000000..3a6da091b78 --- /dev/null +++ b/samples/client/petstore/csharp/SwaggerClientWithPropertyChanged/src/IO.Swagger/Client/JsonSubTypes.cs @@ -0,0 +1,272 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; + +namespace JsonSubTypes +{ + // Copied from project https://github.com/manuc66/JsonSubTypes + // https://raw.githubusercontent.com/manuc66/JsonSubTypes/07403192ea3f4959f6d42f5966ac56ceb0d6095b/JsonSubTypes/JsonSubtypes.cs + + public class JsonSubtypes : JsonConverter + { + [AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface, AllowMultiple = true)] + public class KnownSubTypeAttribute : Attribute + { + public Type SubType { get; private set; } + public object AssociatedValue { get; private set; } + + public KnownSubTypeAttribute(Type subType, object associatedValue) + { + SubType = subType; + AssociatedValue = associatedValue; + } + } + [AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface, AllowMultiple = true)] + public class KnownSubTypeWithPropertyAttribute : Attribute + { + public Type SubType { get; private set; } + public string PropertyName { get; private set; } + + public KnownSubTypeWithPropertyAttribute(Type subType, string propertyName) + { + SubType = subType; + PropertyName = propertyName; + } + } + + private readonly string _typeMappingPropertyName; + + private bool _isInsideRead; + private JsonReader _reader; + + public override bool CanRead + { + get + { + if (!_isInsideRead) + return true; + + return !string.IsNullOrEmpty(_reader.Path); + } + } + + public sealed override bool CanWrite + { + get { return false; } + } + + public JsonSubtypes() + { + } + + public JsonSubtypes(string typeMappingPropertyName) + { + _typeMappingPropertyName = typeMappingPropertyName; + } + + public override bool CanConvert(Type objectType) + { + return _typeMappingPropertyName != null; + } + + public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) + { + throw new NotImplementedException(); + } + + public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) + { + if (reader.TokenType == JsonToken.Comment) + reader.Read(); + + switch (reader.TokenType) + { + case JsonToken.Null: + return null; + case JsonToken.StartArray: + return ReadArray(reader, objectType, serializer); + case JsonToken.StartObject: + return ReadObject(reader, objectType, serializer); + default: + throw new Exception("Array: Unrecognized token: " + reader.TokenType); + } + } + + private IList ReadArray(JsonReader reader, Type targetType, JsonSerializer serializer) + { + var elementType = GetElementType(targetType); + + var list = CreateCompatibleList(targetType, elementType); + + while (reader.TokenType != JsonToken.EndArray && reader.Read()) + { + switch (reader.TokenType) + { + case JsonToken.Null: + list.Add(reader.Value); + break; + case JsonToken.Comment: + break; + case JsonToken.StartObject: + list.Add(ReadObject(reader, elementType, serializer)); + break; + case JsonToken.EndArray: + break; + default: + throw new Exception("Array: Unrecognized token: " + reader.TokenType); + } + } + if (targetType.IsArray) + { + var array = Array.CreateInstance(targetType.GetElementType(), list.Count); + list.CopyTo(array, 0); + list = array; + } + return list; + } + + private static IList CreateCompatibleList(Type targetContainerType, Type elementType) + { + IList list; + if (targetContainerType.IsArray || targetContainerType.GetTypeInfo().IsAbstract) + { + list = (IList)Activator.CreateInstance(typeof(List<>).MakeGenericType(elementType)); + } + else + { + list = (IList)Activator.CreateInstance(targetContainerType); + } + return list; + } + + private static Type GetElementType(Type arrayOrGenericContainer) + { + Type elementType; + if (arrayOrGenericContainer.IsArray) + { + elementType = arrayOrGenericContainer.GetElementType(); + } + else + { + elementType = arrayOrGenericContainer.GenericTypeArguments[0]; + } + return elementType; + } + + private object ReadObject(JsonReader reader, Type objectType, JsonSerializer serializer) + { + var jObject = JObject.Load(reader); + + var targetType = GetType(jObject, objectType) ?? objectType; + + return _ReadJson(CreateAnotherReader(jObject, reader), targetType, null, serializer); + } + + private static JsonReader CreateAnotherReader(JObject jObject, JsonReader reader) + { + var jObjectReader = jObject.CreateReader(); + jObjectReader.Culture = reader.Culture; + jObjectReader.CloseInput = reader.CloseInput; + jObjectReader.SupportMultipleContent = reader.SupportMultipleContent; + jObjectReader.DateTimeZoneHandling = reader.DateTimeZoneHandling; + jObjectReader.FloatParseHandling = reader.FloatParseHandling; + jObjectReader.DateFormatString = reader.DateFormatString; + jObjectReader.DateParseHandling = reader.DateParseHandling; + return jObjectReader; + } + + public Type GetType(JObject jObject, Type parentType) + { + if (_typeMappingPropertyName == null) + { + return GetTypeByPropertyPresence(jObject, parentType); + } + return GetTypeFromDiscriminatorValue(jObject, parentType); + } + + private static Type GetTypeByPropertyPresence(JObject jObject, Type parentType) + { + foreach (var type in parentType.GetTypeInfo().GetCustomAttributes()) + { + JToken ignore; + if (jObject.TryGetValue(type.PropertyName, out ignore)) + { + return type.SubType; + } + } + return null; + } + + private Type GetTypeFromDiscriminatorValue(JObject jObject, Type parentType) + { + JToken jToken; + if (!jObject.TryGetValue(_typeMappingPropertyName, out jToken)) return null; + + var discriminatorValue = jToken.ToObject(); + if (discriminatorValue == null) return null; + + var typeMapping = GetSubTypeMapping(parentType); + if (typeMapping.Any()) + { + return GetTypeFromMapping(typeMapping, discriminatorValue); + } + return GetTypeByName(discriminatorValue as string, parentType); + } + + private static Type GetTypeByName(string typeName, Type parentType) + { + if (typeName == null) + return null; + + var insideAssembly = parentType.GetTypeInfo().Assembly; + + var typeByName = insideAssembly.GetType(typeName); + if (typeByName == null) + { + var searchLocation = parentType.FullName.Substring(0, parentType.FullName.Length - parentType.Name.Length); + typeByName = insideAssembly.GetType(searchLocation + typeName, false, true); + } + return typeByName; + } + + private static Type GetTypeFromMapping(IReadOnlyDictionary typeMapping, object discriminatorValue) + { + var targetlookupValueType = typeMapping.First().Key.GetType(); + var lookupValue = ConvertJsonValueToType(discriminatorValue, targetlookupValueType); + + Type targetType; + return typeMapping.TryGetValue(lookupValue, out targetType) ? targetType : null; + } + + private static Dictionary GetSubTypeMapping(Type type) + { + return type.GetTypeInfo().GetCustomAttributes().ToDictionary(x => x.AssociatedValue, x => x.SubType); + } + + private static object ConvertJsonValueToType(object objectType, Type targetlookupValueType) + { + if (targetlookupValueType.GetTypeInfo().IsEnum) + return Enum.ToObject(targetlookupValueType, objectType); + + return Convert.ChangeType(objectType, targetlookupValueType); + } + + protected object _ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) + { + _reader = reader; + _isInsideRead = true; + try + { + return serializer.Deserialize(reader, objectType); + } + finally + { + _isInsideRead = false; + } + } + } +} diff --git a/samples/client/petstore/csharp/SwaggerClientWithPropertyChanged/src/IO.Swagger/Model/AdditionalPropertiesClass.cs b/samples/client/petstore/csharp/SwaggerClientWithPropertyChanged/src/IO.Swagger/Model/AdditionalPropertiesClass.cs index 835a6438372..12d2321845a 100644 --- a/samples/client/petstore/csharp/SwaggerClientWithPropertyChanged/src/IO.Swagger/Model/AdditionalPropertiesClass.cs +++ b/samples/client/petstore/csharp/SwaggerClientWithPropertyChanged/src/IO.Swagger/Model/AdditionalPropertiesClass.cs @@ -102,13 +102,13 @@ namespace IO.Swagger.Model return ( this.MapProperty == input.MapProperty || - (this.MapProperty != null && - this.MapProperty.SequenceEqual(input.MapProperty)) + this.MapProperty != null && + this.MapProperty.SequenceEqual(input.MapProperty) ) && ( this.MapOfMapProperty == input.MapOfMapProperty || - (this.MapOfMapProperty != null && - this.MapOfMapProperty.SequenceEqual(input.MapOfMapProperty)) + this.MapOfMapProperty != null && + this.MapOfMapProperty.SequenceEqual(input.MapOfMapProperty) ); } diff --git a/samples/client/petstore/csharp/SwaggerClientWithPropertyChanged/src/IO.Swagger/Model/Animal.cs b/samples/client/petstore/csharp/SwaggerClientWithPropertyChanged/src/IO.Swagger/Model/Animal.cs index ef827f20250..e99145ac092 100644 --- a/samples/client/petstore/csharp/SwaggerClientWithPropertyChanged/src/IO.Swagger/Model/Animal.cs +++ b/samples/client/petstore/csharp/SwaggerClientWithPropertyChanged/src/IO.Swagger/Model/Animal.cs @@ -19,6 +19,7 @@ using System.Collections.ObjectModel; using System.Runtime.Serialization; using Newtonsoft.Json; using Newtonsoft.Json.Converters; +using JsonSubTypes; using PropertyChanged; using System.ComponentModel; using System.ComponentModel.DataAnnotations; @@ -30,6 +31,9 @@ namespace IO.Swagger.Model /// Animal /// [DataContract] + [JsonConverter(typeof(JsonSubtypes), "className")] + [JsonSubtypes.KnownSubType(typeof(Dog), "Dog")] + [JsonSubtypes.KnownSubType(typeof(Cat), "Cat")] [ImplementPropertyChanged] public partial class Animal : IEquatable, IValidatableObject { @@ -95,7 +99,7 @@ namespace IO.Swagger.Model /// Returns the JSON string presentation of the object /// /// JSON string presentation of the object - public string ToJson() + public virtual string ToJson() { return JsonConvert.SerializeObject(this, Formatting.Indented); } @@ -176,6 +180,16 @@ namespace IO.Swagger.Model /// Validation context /// Validation Result IEnumerable IValidatableObject.Validate(ValidationContext validationContext) + { + return this.BaseValidate(validationContext); + } + + /// + /// To validate all properties of the instance + /// + /// Validation context + /// Validation Result + protected IEnumerable BaseValidate(ValidationContext validationContext) { yield break; } diff --git a/samples/client/petstore/csharp/SwaggerClientWithPropertyChanged/src/IO.Swagger/Model/AnimalFarm.cs b/samples/client/petstore/csharp/SwaggerClientWithPropertyChanged/src/IO.Swagger/Model/AnimalFarm.cs index c42cc160bf3..962b8299b1f 100644 --- a/samples/client/petstore/csharp/SwaggerClientWithPropertyChanged/src/IO.Swagger/Model/AnimalFarm.cs +++ b/samples/client/petstore/csharp/SwaggerClientWithPropertyChanged/src/IO.Swagger/Model/AnimalFarm.cs @@ -37,7 +37,7 @@ namespace IO.Swagger.Model /// Initializes a new instance of the class. /// [JsonConstructorAttribute] - public AnimalFarm() + public AnimalFarm() : base() { } @@ -49,6 +49,7 @@ namespace IO.Swagger.Model { var sb = new StringBuilder(); sb.Append("class AnimalFarm {\n"); + sb.Append(" ").Append(base.ToString().Replace("\n", "\n ")).Append("\n"); sb.Append("}\n"); return sb.ToString(); } @@ -57,7 +58,7 @@ namespace IO.Swagger.Model /// Returns the JSON string presentation of the object /// /// JSON string presentation of the object - public new string ToJson() + public string ToJson() { return JsonConvert.SerializeObject(this, Formatting.Indented); } @@ -82,7 +83,7 @@ namespace IO.Swagger.Model if (input == null) return false; - return false; + return base.Equals(input); } /// @@ -93,7 +94,7 @@ namespace IO.Swagger.Model { unchecked // Overflow is fine, just wrap { - int hashCode = 41; + int hashCode = base.GetHashCode(); return hashCode; } } diff --git a/samples/client/petstore/csharp/SwaggerClientWithPropertyChanged/src/IO.Swagger/Model/ArrayOfArrayOfNumberOnly.cs b/samples/client/petstore/csharp/SwaggerClientWithPropertyChanged/src/IO.Swagger/Model/ArrayOfArrayOfNumberOnly.cs index a134c17caea..f7d7fd178fe 100644 --- a/samples/client/petstore/csharp/SwaggerClientWithPropertyChanged/src/IO.Swagger/Model/ArrayOfArrayOfNumberOnly.cs +++ b/samples/client/petstore/csharp/SwaggerClientWithPropertyChanged/src/IO.Swagger/Model/ArrayOfArrayOfNumberOnly.cs @@ -93,8 +93,8 @@ namespace IO.Swagger.Model return ( this.ArrayArrayNumber == input.ArrayArrayNumber || - (this.ArrayArrayNumber != null && - this.ArrayArrayNumber.SequenceEqual(input.ArrayArrayNumber)) + this.ArrayArrayNumber != null && + this.ArrayArrayNumber.SequenceEqual(input.ArrayArrayNumber) ); } diff --git a/samples/client/petstore/csharp/SwaggerClientWithPropertyChanged/src/IO.Swagger/Model/ArrayOfNumberOnly.cs b/samples/client/petstore/csharp/SwaggerClientWithPropertyChanged/src/IO.Swagger/Model/ArrayOfNumberOnly.cs index ed2f0e4d26e..72022dfff14 100644 --- a/samples/client/petstore/csharp/SwaggerClientWithPropertyChanged/src/IO.Swagger/Model/ArrayOfNumberOnly.cs +++ b/samples/client/petstore/csharp/SwaggerClientWithPropertyChanged/src/IO.Swagger/Model/ArrayOfNumberOnly.cs @@ -93,8 +93,8 @@ namespace IO.Swagger.Model return ( this.ArrayNumber == input.ArrayNumber || - (this.ArrayNumber != null && - this.ArrayNumber.SequenceEqual(input.ArrayNumber)) + this.ArrayNumber != null && + this.ArrayNumber.SequenceEqual(input.ArrayNumber) ); } diff --git a/samples/client/petstore/csharp/SwaggerClientWithPropertyChanged/src/IO.Swagger/Model/ArrayTest.cs b/samples/client/petstore/csharp/SwaggerClientWithPropertyChanged/src/IO.Swagger/Model/ArrayTest.cs index 9b084bf1029..64473d4d14f 100644 --- a/samples/client/petstore/csharp/SwaggerClientWithPropertyChanged/src/IO.Swagger/Model/ArrayTest.cs +++ b/samples/client/petstore/csharp/SwaggerClientWithPropertyChanged/src/IO.Swagger/Model/ArrayTest.cs @@ -111,18 +111,18 @@ namespace IO.Swagger.Model return ( this.ArrayOfString == input.ArrayOfString || - (this.ArrayOfString != null && - this.ArrayOfString.SequenceEqual(input.ArrayOfString)) + this.ArrayOfString != null && + this.ArrayOfString.SequenceEqual(input.ArrayOfString) ) && ( this.ArrayArrayOfInteger == input.ArrayArrayOfInteger || - (this.ArrayArrayOfInteger != null && - this.ArrayArrayOfInteger.SequenceEqual(input.ArrayArrayOfInteger)) + this.ArrayArrayOfInteger != null && + this.ArrayArrayOfInteger.SequenceEqual(input.ArrayArrayOfInteger) ) && ( this.ArrayArrayOfModel == input.ArrayArrayOfModel || - (this.ArrayArrayOfModel != null && - this.ArrayArrayOfModel.SequenceEqual(input.ArrayArrayOfModel)) + this.ArrayArrayOfModel != null && + this.ArrayArrayOfModel.SequenceEqual(input.ArrayArrayOfModel) ); } diff --git a/samples/client/petstore/csharp/SwaggerClientWithPropertyChanged/src/IO.Swagger/Model/Cat.cs b/samples/client/petstore/csharp/SwaggerClientWithPropertyChanged/src/IO.Swagger/Model/Cat.cs index 70745b083c0..ec8d4fb6030 100644 --- a/samples/client/petstore/csharp/SwaggerClientWithPropertyChanged/src/IO.Swagger/Model/Cat.cs +++ b/samples/client/petstore/csharp/SwaggerClientWithPropertyChanged/src/IO.Swagger/Model/Cat.cs @@ -41,44 +41,12 @@ namespace IO.Swagger.Model /// /// Initializes a new instance of the class. /// - /// ClassName (required). - /// Color (default to "red"). /// Declawed. - public Cat(string ClassName = default(string), string Color = "red", bool? Declawed = default(bool?)) + public Cat(bool? Declawed = default(bool?), string ClassName = "Cat", string Color = "red") : base(ClassName, Color) { - // to ensure "ClassName" is required (not null) - if (ClassName == null) - { - throw new InvalidDataException("ClassName is a required property for Cat and cannot be null"); - } - else - { - this.ClassName = ClassName; - } - // use default value if no "Color" provided - if (Color == null) - { - this.Color = "red"; - } - else - { - this.Color = Color; - } this.Declawed = Declawed; } - /// - /// Gets or Sets ClassName - /// - [DataMember(Name="className", EmitDefaultValue=false)] - public string ClassName { get; set; } - - /// - /// Gets or Sets Color - /// - [DataMember(Name="color", EmitDefaultValue=false)] - public string Color { get; set; } - /// /// Gets or Sets Declawed /// @@ -93,8 +61,7 @@ namespace IO.Swagger.Model { var sb = new StringBuilder(); sb.Append("class Cat {\n"); - sb.Append(" ClassName: ").Append(ClassName).Append("\n"); - sb.Append(" Color: ").Append(Color).Append("\n"); + sb.Append(" ").Append(base.ToString().Replace("\n", "\n ")).Append("\n"); sb.Append(" Declawed: ").Append(Declawed).Append("\n"); sb.Append("}\n"); return sb.ToString(); @@ -104,7 +71,7 @@ namespace IO.Swagger.Model /// Returns the JSON string presentation of the object /// /// JSON string presentation of the object - public new string ToJson() + public override string ToJson() { return JsonConvert.SerializeObject(this, Formatting.Indented); } @@ -129,17 +96,7 @@ namespace IO.Swagger.Model if (input == null) return false; - return - ( - this.ClassName == input.ClassName || - (this.ClassName != null && - this.ClassName.Equals(input.ClassName)) - ) && - ( - this.Color == input.Color || - (this.Color != null && - this.Color.Equals(input.Color)) - ) && + return base.Equals(input) && ( this.Declawed == input.Declawed || (this.Declawed != null && @@ -155,11 +112,7 @@ namespace IO.Swagger.Model { unchecked // Overflow is fine, just wrap { - int hashCode = 41; - if (this.ClassName != null) - hashCode = hashCode * 59 + this.ClassName.GetHashCode(); - if (this.Color != null) - hashCode = hashCode * 59 + this.Color.GetHashCode(); + int hashCode = base.GetHashCode(); if (this.Declawed != null) hashCode = hashCode * 59 + this.Declawed.GetHashCode(); return hashCode; @@ -193,6 +146,7 @@ namespace IO.Swagger.Model /// Validation Result IEnumerable IValidatableObject.Validate(ValidationContext validationContext) { + foreach(var x in BaseValidate(validationContext)) yield return x; yield break; } } diff --git a/samples/client/petstore/csharp/SwaggerClientWithPropertyChanged/src/IO.Swagger/Model/Dog.cs b/samples/client/petstore/csharp/SwaggerClientWithPropertyChanged/src/IO.Swagger/Model/Dog.cs index 0d66a97f4dc..12f06f9ae53 100644 --- a/samples/client/petstore/csharp/SwaggerClientWithPropertyChanged/src/IO.Swagger/Model/Dog.cs +++ b/samples/client/petstore/csharp/SwaggerClientWithPropertyChanged/src/IO.Swagger/Model/Dog.cs @@ -41,44 +41,12 @@ namespace IO.Swagger.Model /// /// Initializes a new instance of the class. /// - /// ClassName (required). - /// Color (default to "red"). /// Breed. - public Dog(string ClassName = default(string), string Color = "red", string Breed = default(string)) + public Dog(string Breed = default(string), string ClassName = "Dog", string Color = "red") : base(ClassName, Color) { - // to ensure "ClassName" is required (not null) - if (ClassName == null) - { - throw new InvalidDataException("ClassName is a required property for Dog and cannot be null"); - } - else - { - this.ClassName = ClassName; - } - // use default value if no "Color" provided - if (Color == null) - { - this.Color = "red"; - } - else - { - this.Color = Color; - } this.Breed = Breed; } - /// - /// Gets or Sets ClassName - /// - [DataMember(Name="className", EmitDefaultValue=false)] - public string ClassName { get; set; } - - /// - /// Gets or Sets Color - /// - [DataMember(Name="color", EmitDefaultValue=false)] - public string Color { get; set; } - /// /// Gets or Sets Breed /// @@ -93,8 +61,7 @@ namespace IO.Swagger.Model { var sb = new StringBuilder(); sb.Append("class Dog {\n"); - sb.Append(" ClassName: ").Append(ClassName).Append("\n"); - sb.Append(" Color: ").Append(Color).Append("\n"); + sb.Append(" ").Append(base.ToString().Replace("\n", "\n ")).Append("\n"); sb.Append(" Breed: ").Append(Breed).Append("\n"); sb.Append("}\n"); return sb.ToString(); @@ -104,7 +71,7 @@ namespace IO.Swagger.Model /// Returns the JSON string presentation of the object /// /// JSON string presentation of the object - public new string ToJson() + public override string ToJson() { return JsonConvert.SerializeObject(this, Formatting.Indented); } @@ -129,17 +96,7 @@ namespace IO.Swagger.Model if (input == null) return false; - return - ( - this.ClassName == input.ClassName || - (this.ClassName != null && - this.ClassName.Equals(input.ClassName)) - ) && - ( - this.Color == input.Color || - (this.Color != null && - this.Color.Equals(input.Color)) - ) && + return base.Equals(input) && ( this.Breed == input.Breed || (this.Breed != null && @@ -155,11 +112,7 @@ namespace IO.Swagger.Model { unchecked // Overflow is fine, just wrap { - int hashCode = 41; - if (this.ClassName != null) - hashCode = hashCode * 59 + this.ClassName.GetHashCode(); - if (this.Color != null) - hashCode = hashCode * 59 + this.Color.GetHashCode(); + int hashCode = base.GetHashCode(); if (this.Breed != null) hashCode = hashCode * 59 + this.Breed.GetHashCode(); return hashCode; @@ -193,6 +146,7 @@ namespace IO.Swagger.Model /// Validation Result IEnumerable IValidatableObject.Validate(ValidationContext validationContext) { + foreach(var x in BaseValidate(validationContext)) yield return x; yield break; } } diff --git a/samples/client/petstore/csharp/SwaggerClientWithPropertyChanged/src/IO.Swagger/Model/EnumArrays.cs b/samples/client/petstore/csharp/SwaggerClientWithPropertyChanged/src/IO.Swagger/Model/EnumArrays.cs index ed7f544d8fa..2776b6ed2fe 100644 --- a/samples/client/petstore/csharp/SwaggerClientWithPropertyChanged/src/IO.Swagger/Model/EnumArrays.cs +++ b/samples/client/petstore/csharp/SwaggerClientWithPropertyChanged/src/IO.Swagger/Model/EnumArrays.cs @@ -148,8 +148,8 @@ namespace IO.Swagger.Model ) && ( this.ArrayEnum == input.ArrayEnum || - (this.ArrayEnum != null && - this.ArrayEnum.SequenceEqual(input.ArrayEnum)) + this.ArrayEnum != null && + this.ArrayEnum.SequenceEqual(input.ArrayEnum) ); } diff --git a/samples/client/petstore/csharp/SwaggerClientWithPropertyChanged/src/IO.Swagger/Model/MapTest.cs b/samples/client/petstore/csharp/SwaggerClientWithPropertyChanged/src/IO.Swagger/Model/MapTest.cs index 4a68a63804d..126eed194a1 100644 --- a/samples/client/petstore/csharp/SwaggerClientWithPropertyChanged/src/IO.Swagger/Model/MapTest.cs +++ b/samples/client/petstore/csharp/SwaggerClientWithPropertyChanged/src/IO.Swagger/Model/MapTest.cs @@ -123,13 +123,13 @@ namespace IO.Swagger.Model return ( this.MapMapOfString == input.MapMapOfString || - (this.MapMapOfString != null && - this.MapMapOfString.SequenceEqual(input.MapMapOfString)) + this.MapMapOfString != null && + this.MapMapOfString.SequenceEqual(input.MapMapOfString) ) && ( this.MapOfEnumString == input.MapOfEnumString || - (this.MapOfEnumString != null && - this.MapOfEnumString.SequenceEqual(input.MapOfEnumString)) + this.MapOfEnumString != null && + this.MapOfEnumString.SequenceEqual(input.MapOfEnumString) ); } diff --git a/samples/client/petstore/csharp/SwaggerClientWithPropertyChanged/src/IO.Swagger/Model/MixedPropertiesAndAdditionalPropertiesClass.cs b/samples/client/petstore/csharp/SwaggerClientWithPropertyChanged/src/IO.Swagger/Model/MixedPropertiesAndAdditionalPropertiesClass.cs index a878e886752..ac512031cb2 100644 --- a/samples/client/petstore/csharp/SwaggerClientWithPropertyChanged/src/IO.Swagger/Model/MixedPropertiesAndAdditionalPropertiesClass.cs +++ b/samples/client/petstore/csharp/SwaggerClientWithPropertyChanged/src/IO.Swagger/Model/MixedPropertiesAndAdditionalPropertiesClass.cs @@ -121,8 +121,8 @@ namespace IO.Swagger.Model ) && ( this.Map == input.Map || - (this.Map != null && - this.Map.SequenceEqual(input.Map)) + this.Map != null && + this.Map.SequenceEqual(input.Map) ); } diff --git a/samples/client/petstore/csharp/SwaggerClientWithPropertyChanged/src/IO.Swagger/Model/Pet.cs b/samples/client/petstore/csharp/SwaggerClientWithPropertyChanged/src/IO.Swagger/Model/Pet.cs index e75655053cc..d57e936bb2d 100644 --- a/samples/client/petstore/csharp/SwaggerClientWithPropertyChanged/src/IO.Swagger/Model/Pet.cs +++ b/samples/client/petstore/csharp/SwaggerClientWithPropertyChanged/src/IO.Swagger/Model/Pet.cs @@ -202,13 +202,13 @@ namespace IO.Swagger.Model ) && ( this.PhotoUrls == input.PhotoUrls || - (this.PhotoUrls != null && - this.PhotoUrls.SequenceEqual(input.PhotoUrls)) + this.PhotoUrls != null && + this.PhotoUrls.SequenceEqual(input.PhotoUrls) ) && ( this.Tags == input.Tags || - (this.Tags != null && - this.Tags.SequenceEqual(input.Tags)) + this.Tags != null && + this.Tags.SequenceEqual(input.Tags) ) && ( this.Status == input.Status ||