diff --git a/XmlSchemaClassGenerator.Tests/Compiler.cs b/XmlSchemaClassGenerator.Tests/Compiler.cs index 6c486073..d5f63d2c 100644 --- a/XmlSchemaClassGenerator.Tests/Compiler.cs +++ b/XmlSchemaClassGenerator.Tests/Compiler.cs @@ -47,6 +47,7 @@ public static CompilationResult GenerateAssembly(Compilation compilation) "System.Private.Xml", "System.Private.Xml.Linq", "System.Runtime", + "System.Runtime.Extensions", "System.Xml.XDocument", "System.Xml.XmlSerializer", }; @@ -104,7 +105,9 @@ public static Assembly GenerateFiles(string name, IEnumerable files, Gen CollectionSettersMode = generatorPrototype.CollectionSettersMode, TextValuePropertyName = generatorPrototype.TextValuePropertyName, EmitOrder = generatorPrototype.EmitOrder, - SeparateClasses = generatorPrototype.SeparateClasses + SeparateClasses = generatorPrototype.SeparateClasses, + CollectionType = generatorPrototype.CollectionType, + CollectionImplementationType = generatorPrototype.CollectionImplementationType }; output.Configuration = gen.Configuration; diff --git a/XmlSchemaClassGenerator.Tests/XmlTests.cs b/XmlSchemaClassGenerator.Tests/XmlTests.cs index 8fa6da13..5238d180 100644 --- a/XmlSchemaClassGenerator.Tests/XmlTests.cs +++ b/XmlSchemaClassGenerator.Tests/XmlTests.cs @@ -379,16 +379,32 @@ public void TestTableau() public void TestSeparateClasses() { var output = new FileWatcherOutputWriter(Path.Combine("output", "Tableau.Separate")); - Compiler.Generate("Tableau.Separate", TableauPattern, - new Generator - { - OutputWriter = output, + Compiler.Generate("Tableau.Separate", TableauPattern, + new Generator + { + OutputWriter = output, SeparateClasses = true, EnableDataBinding = true }); TestSamples("Tableau.Separate", TableauPattern); } + [Fact, TestPriority(1)] + [UseCulture("en-US")] + public void TestArray() + { + var output = new FileWatcherOutputWriter(Path.Combine("output", "Tableau.Array")); + Compiler.Generate("Tableau.Array", TableauPattern, + new Generator + { + OutputWriter = output, + EnableDataBinding = true, + CollectionType = typeof(System.Array), + CollectionSettersMode = CollectionSettersMode.Public + }); + TestSamples("Tableau.Array", TableauPattern); + } + [Fact, TestPriority(1)] [UseCulture("en-US")] public void TestDtsx() diff --git a/XmlSchemaClassGenerator/TypeModel.cs b/XmlSchemaClassGenerator/TypeModel.cs index b8f3aa74..961d0c16 100644 --- a/XmlSchemaClassGenerator/TypeModel.cs +++ b/XmlSchemaClassGenerator/TypeModel.cs @@ -717,7 +717,7 @@ private bool IsNullableValueType { return DefaultValue == null && IsNullable && !(IsCollection || IsArray) && !IsList - && ((PropertyType is EnumModel) || (PropertyType is SimpleModel && ((SimpleModel)PropertyType).ValueType.IsValueType)); + && ((PropertyType is EnumModel) || (PropertyType is SimpleModel model && model.ValueType.IsValueType)); } } @@ -727,7 +727,7 @@ private bool IsNillableValueType { return IsNillable && !(IsCollection || IsArray) - && ((PropertyType is EnumModel) || (PropertyType is SimpleModel && ((SimpleModel)PropertyType).ValueType.IsValueType)); + && ((PropertyType is EnumModel) || (PropertyType is SimpleModel model && model.ValueType.IsValueType)); } } @@ -1056,7 +1056,9 @@ public void AddMembersTo(CodeTypeDeclaration typeDeclaration, bool withDataBindi specifiedProperty.Attributes = MemberAttributes.Public | MemberAttributes.Final; var listReference = new CodePropertyReferenceExpression(new CodeThisReferenceExpression(), Name); - var countReference = new CodePropertyReferenceExpression(listReference, "Count"); + var collectionType = Configuration.CollectionImplementationType ?? Configuration.CollectionType; + var countProperty = collectionType == typeof(System.Array) ? "Length" : "Count"; + var countReference = new CodePropertyReferenceExpression(listReference, countProperty); var notZeroExpression = new CodeBinaryOperatorExpression(countReference, CodeBinaryOperatorType.IdentityInequality, new CodePrimitiveExpression(0)); if (Configuration.CollectionSettersMode == CollectionSettersMode.PublicWithoutConstructorInitialization) { @@ -1082,6 +1084,7 @@ public void AddMembersTo(CodeTypeDeclaration typeDeclaration, bool withDataBindi if ((IsCollection || isArray || (IsList && IsAttribute)) && Configuration.CollectionSettersMode != CollectionSettersMode.PublicWithoutConstructorInitialization) { var constructor = typeDeclaration.Members.OfType().FirstOrDefault(); + if (constructor == null) { constructor = new CodeConstructor { Attributes = MemberAttributes.Public | MemberAttributes.Final }; @@ -1090,10 +1093,24 @@ public void AddMembersTo(CodeTypeDeclaration typeDeclaration, bool withDataBindi constructor.Comments.AddRange(DocumentationModel.GetComments(constructorDocs).ToArray()); typeDeclaration.Members.Add(constructor); } + var listReference = requiresBackingField ? (CodeExpression)new CodeFieldReferenceExpression(new CodeThisReferenceExpression(), backingField.Name) : new CodePropertyReferenceExpression(new CodeThisReferenceExpression(), Name); - var initTypeReference = propertyType.GetReferenceFor(OwningType.Namespace, collection: true, forInit: true, attribute: IsAttribute); - var initExpression = new CodeObjectCreateExpression(initTypeReference); + var collectionType = Configuration.CollectionImplementationType ?? Configuration.CollectionType; + + CodeExpression initExpression; + + if (collectionType == typeof(System.Array)) + { + var initTypeReference = propertyType.GetReferenceFor(OwningType.Namespace, collection: false, forInit: true, attribute: IsAttribute); + initExpression = new CodeArrayCreateExpression(initTypeReference); + } + else + { + var initTypeReference = propertyType.GetReferenceFor(OwningType.Namespace, collection: true, forInit: true, attribute: IsAttribute); + initExpression = new CodeObjectCreateExpression(initTypeReference); + } + constructor.Statements.Add(new CodeAssignStatement(listReference, initExpression)); } @@ -1350,21 +1367,26 @@ public SimpleModel(GeneratorConfiguration configuration) public static string GetCollectionDefinitionName(string typeName, GeneratorConfiguration configuration) { - var typeRef = new CodeTypeReference(configuration.CollectionType, configuration.CodeTypeReferenceOptions); - return GetFullTypeName(typeName, configuration, typeRef); + var type = configuration.CollectionType; + var typeRef = new CodeTypeReference(type, configuration.CodeTypeReferenceOptions); + return GetFullTypeName(typeName, typeRef, type); } public static string GetCollectionImplementationName(string typeName, GeneratorConfiguration configuration) { - var typeRef = new CodeTypeReference(configuration.CollectionImplementationType ?? configuration.CollectionType, configuration.CodeTypeReferenceOptions); - return GetFullTypeName(typeName, configuration, typeRef); + var type = configuration.CollectionImplementationType ?? configuration.CollectionType; + var typeRef = new CodeTypeReference(type, configuration.CodeTypeReferenceOptions); + return GetFullTypeName(typeName, typeRef, type); } - private static string GetFullTypeName(string typeName, GeneratorConfiguration configuration, CodeTypeReference typeRef) + private static string GetFullTypeName(string typeName, CodeTypeReference typeRef, Type type) { - if (configuration.CollectionType.IsGenericTypeDefinition) - { + if (type.IsGenericTypeDefinition) typeRef.TypeArguments.Add(typeName); + else if (type == typeof(System.Array)) + { + typeRef.ArrayElementType = new CodeTypeReference(typeName); + typeRef.ArrayRank = 1; } var typeOfExpr = new CodeTypeOfExpression(typeRef); var writer = new System.IO.StringWriter(); @@ -1397,14 +1419,14 @@ public override CodeTypeReference GetReferenceFor(NamespaceModel referencingName if (collection) { - if (forInit) - { - type = (Configuration.CollectionImplementationType ?? Configuration.CollectionType).MakeGenericType(type); - } + var collectionType = forInit ? (Configuration.CollectionImplementationType ?? Configuration.CollectionType) : Configuration.CollectionType; + + if (collectionType.IsGenericType) + type = collectionType.MakeGenericType(type); + else if (collectionType == typeof(System.Array)) + type = type.MakeArrayType(); else - { - type = Configuration.CollectionType.MakeGenericType(type); - } + type = collectionType; } return new CodeTypeReference(type, Configuration.CodeTypeReferenceOptions);