Skip to content

Commit 732fcd2

Browse files
author
Michael Ganss
committed
Add UseArrayItemAttribute option (fixes #313)
1 parent a317132 commit 732fcd2

7 files changed

Lines changed: 80 additions & 13 deletions

File tree

XmlSchemaClassGenerator.Console/Program.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ static void Main(string[] args)
5656
var netCoreSpecificCode = false;
5757
var nullableReferenceAttributes = false;
5858
var generateCommandLineArgs = true;
59+
var useArrayItemAttribute = true;
5960

6061
var options = new OptionSet {
6162
{ "h|help", "show this message and exit", v => showHelp = v != null },
@@ -129,6 +130,7 @@ A file name may be given by appending a pipe sign (|) followed by a file name (l
129130
{ "gc|generatedCodeAttribute", "add version information to GeneratedCodeAttribute (default is true)", v => createGeneratedCodeAttributeVersion = v != null },
130131
{ "nc|netCore", "generate .NET Core specific code that might not work with .NET Framework (default is false)", v => netCoreSpecificCode = v != null },
131132
{ "nr|nullableReferenceAttributes", "generate attributes for nullable reference types (default is false)", v => nullableReferenceAttributes = v != null },
133+
{ "ar|useArrayItemAttribute", "use ArrayItemAttribute for sequences with single elements (default is true)", v => useArrayItemAttribute = v != null },
132134
{ "ca|commandArgs", "generate a comment with the exact command line arguments that were used to generate the source code (default is true)", v => generateCommandLineArgs = v != null },
133135
};
134136

@@ -207,6 +209,7 @@ A file name may be given by appending a pipe sign (|) followed by a file name (l
207209
NetCoreSpecificCode = netCoreSpecificCode,
208210
EnableNullableReferenceAttributes = nullableReferenceAttributes,
209211
GenerateCommandLineArgumentsComment = generateCommandLineArgs,
212+
UseArrayItemAttribute = useArrayItemAttribute,
210213
};
211214

212215
generator.CommentLanguages.AddRange(commentLanguages);

XmlSchemaClassGenerator.Tests/Compiler.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,8 @@ public static Assembly GenerateFiles(string name, IEnumerable<string> files, Gen
114114
CreateGeneratedCodeAttributeVersion = generatorPrototype.CreateGeneratedCodeAttributeVersion,
115115
NetCoreSpecificCode = generatorPrototype.NetCoreSpecificCode,
116116
EnableNullableReferenceAttributes = generatorPrototype.EnableNullableReferenceAttributes,
117-
NamingScheme = generatorPrototype.NamingScheme
117+
NamingScheme = generatorPrototype.NamingScheme,
118+
UseArrayItemAttribute = generatorPrototype.UseArrayItemAttribute,
118119
};
119120

120121
gen.CommentLanguages.Clear();

XmlSchemaClassGenerator.Tests/XmlTests.cs

Lines changed: 54 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ private static IEnumerable<string> ConvertXml(string name, IEnumerable<string> x
6464
CollectionType = generatorPrototype.CollectionType,
6565
CollectionImplementationType = generatorPrototype.CollectionImplementationType,
6666
CollectionSettersMode = generatorPrototype.CollectionSettersMode,
67+
UseArrayItemAttribute = generatorPrototype.UseArrayItemAttribute,
6768
};
6869

6970
gen.CommentLanguages.Clear();
@@ -2371,20 +2372,20 @@ void UnknownAttributeHandler(object sender, XmlAttributeEventArgs e)
23712372

23722373
[Fact, TestPriority(1)]
23732374
[UseCulture("en-US")]
2374-
public void TestNullableReferenceAttributes()
2375+
public void TestNullableReferenceAttributes()
23752376
{
23762377
var files = Glob.ExpandNames(NullableReferenceAttributesPattern).OrderByDescending(f => f);
2377-
var generator = new Generator
2378+
var generator = new Generator
23782379
{
23792380
EnableNullableReferenceAttributes = true,
23802381
UseShouldSerializePattern = true,
2381-
NamespaceProvider = new NamespaceProvider
2382+
NamespaceProvider = new NamespaceProvider
23822383
{
23832384
GenerateNamespace = key => "Test"
23842385
}
23852386
};
23862387
var assembly = Compiler.Generate(nameof(TestNullableReferenceAttributes), NullableReferenceAttributesPattern, generator);
2387-
void assertNullable(string typename, bool nullable)
2388+
void assertNullable(string typename, bool nullable)
23882389
{
23892390
Type c = assembly.GetType(typename);
23902391
var property = c.GetProperty("Text");
@@ -2528,5 +2529,54 @@ public partial class Elem
25282529
}}
25292530
", csharp);
25302531
}
2532+
2533+
[Fact]
2534+
public void TestArrayItemAttribute()
2535+
{
2536+
// see https://github.com/mganss/XmlSchemaClassGenerator/issues/313
2537+
2538+
var xsd =
2539+
@"<?xml version=""1.0"" encoding=""UTF-8""?>
2540+
2541+
<xs:schema xmlns:xs=""http://www.w3.org/2001/XMLSchema""
2542+
xmlns=""test_generation_namespace/common.xsd""
2543+
xmlns:ct=""test_generation_namespace/commontypes.xsd""
2544+
targetNamespace=""test_generation_namespace/common.xsd""
2545+
version=""1.1""
2546+
elementFormDefault=""qualified""
2547+
attributeFormDefault=""unqualified"">
2548+
<xs:import namespace=""test_generation_namespace/commontypes.xsd"" schemaLocation=""TheCommonTypes.xsd""/>
2549+
<xs:complexType name=""T_NameValue"">
2550+
<xs:sequence>
2551+
<xs:element name=""Name"" type=""xs:string""/>
2552+
<xs:element name=""Value"" type=""xs:string"" minOccurs=""0""/>
2553+
</xs:sequence>
2554+
</xs:complexType>
2555+
<xs:complexType name=""T_OptionList"">
2556+
<xs:sequence>
2557+
<xs:element name=""Option"" type=""T_NameValue"" minOccurs=""0"" maxOccurs=""unbounded""/>
2558+
</xs:sequence>
2559+
</xs:complexType>
2560+
<xs:complexType name=""T_Application"">
2561+
<xs:sequence>
2562+
<xs:element name=""OptionList"" type=""T_OptionList"" minOccurs=""0""/>
2563+
</xs:sequence>
2564+
</xs:complexType>
2565+
</xs:schema>";
2566+
var generator = new Generator
2567+
{
2568+
IntegerDataType = typeof(int),
2569+
GenerateNullables = true,
2570+
CollectionType = typeof(System.Array),
2571+
CollectionSettersMode = CollectionSettersMode.Public,
2572+
UseArrayItemAttribute = false
2573+
};
2574+
var contents = ConvertXml(nameof(TestArrayItemAttribute), new[] { xsd }, generator).ToArray();
2575+
var assembly = Compiler.Compile(nameof(TestArrayItemAttribute), contents);
2576+
var applicationType = assembly.GetType("Test_Generation_Namespace.T_Application");
2577+
Assert.NotNull(applicationType);
2578+
var optionList = applicationType.GetProperty("OptionList");
2579+
Assert.Equal("Test_Generation_Namespace.T_OptionList", optionList.PropertyType.FullName);
2580+
}
25312581
}
25322582
}

XmlSchemaClassGenerator/CodeUtilities.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -245,7 +245,7 @@ public static string GetUniqueTypeName(this NamespaceModel model, string name)
245245
var n = name;
246246
var i = 2;
247247

248-
while (model.Types.ContainsKey(n) && !(model.Types[n] is SimpleModel))
248+
while (model.Types.ContainsKey(n) && model.Types[n] is not SimpleModel)
249249
{
250250
n = name + i;
251251
i++;

XmlSchemaClassGenerator/Generator.cs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ public bool GenerateNullables
115115
set { _configuration.GenerateNullables = value; }
116116
}
117117

118-
public bool EnableNullableReferenceAttributes
118+
public bool EnableNullableReferenceAttributes
119119
{
120120
get { return _configuration.EnableNullableReferenceAttributes; }
121121
set { _configuration.EnableNullableReferenceAttributes = value; }
@@ -294,6 +294,12 @@ public bool NetCoreSpecificCode
294294
set { _configuration.NetCoreSpecificCode = value; }
295295
}
296296

297+
public bool UseArrayItemAttribute
298+
{
299+
get { return _configuration.UseArrayItemAttribute; }
300+
set { _configuration.UseArrayItemAttribute = value;}
301+
}
302+
297303
public bool GenerateCommandLineArgumentsComment
298304
{
299305
get { return _configuration.GenerateCommandLineArgumentsComment; }

XmlSchemaClassGenerator/GeneratorConfiguration.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -320,5 +320,11 @@ public void WriteLog(string message)
320320
/// A provider to obtain the command line arguments of the tool.
321321
/// </summary>
322322
public CommandLineArgumentsProvider CommandLineArgumentsProvider { get; set; }
323+
324+
/// <summary>
325+
/// Enables use of <see cref="System.Xml.Serialization.XmlArrayItemAttribute"/>
326+
/// for sequences with single elements. Default is true.
327+
/// </summary>
328+
public bool UseArrayItemAttribute { get; set; } = true;
323329
}
324330
}

XmlSchemaClassGenerator/TypeModel.cs

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -328,7 +328,7 @@ public override CodeTypeDeclaration Generate()
328328
if (IsAbstract)
329329
classDeclaration.TypeAttributes |= System.Reflection.TypeAttributes.Abstract;
330330

331-
if (Configuration.EnableDataBinding && !(BaseClass is ClassModel))
331+
if (Configuration.EnableDataBinding && BaseClass is not ClassModel)
332332
{
333333
var propertyChangedEvent = new CodeMemberEvent()
334334
{
@@ -432,7 +432,7 @@ public override CodeTypeDeclaration Generate()
432432
classDeclaration.BaseTypes.Add(CodeUtilities.CreateTypeReference(typeof(INotifyPropertyChanged), Configuration));
433433
}
434434

435-
if (Configuration.EntityFramework && !(BaseClass is ClassModel))
435+
if (Configuration.EntityFramework && BaseClass is not ClassModel)
436436
{
437437
// generate key
438438
var keyProperty = Properties.FirstOrDefault(p => p.Name.ToLowerInvariant() == "id")
@@ -729,7 +729,8 @@ public bool IsArray
729729
{
730730
get
731731
{
732-
return !IsCollection && !IsAttribute && !IsList && TypeClassModel != null
732+
return Configuration.UseArrayItemAttribute
733+
&& !IsCollection && !IsAttribute && !IsList && TypeClassModel != null
733734
&& TypeClassModel.BaseClass == null
734735
&& TypeClassModel.Properties.Count == 1
735736
&& !TypeClassModel.Properties[0].IsAttribute && !TypeClassModel.Properties[0].IsAny
@@ -752,9 +753,9 @@ private bool IsNullableValueType
752753
}
753754
}
754755

755-
private bool IsNullableReferenceType
756+
private bool IsNullableReferenceType
756757
{
757-
get
758+
get
758759
{
759760
return DefaultValue == null
760761
&& IsNullable && (IsCollection || IsArray || IsList || PropertyType is ClassModel || PropertyType is SimpleModel model && !model.ValueType.IsValueType);
@@ -1124,7 +1125,7 @@ public void AddMembersTo(CodeTypeDeclaration typeDeclaration, bool withDataBindi
11241125
typeDeclaration.Members.Add(specifiedProperty);
11251126
}
11261127

1127-
if (isNullableReferenceType && Configuration.EnableNullableReferenceAttributes)
1128+
if (isNullableReferenceType && Configuration.EnableNullableReferenceAttributes)
11281129
{
11291130
member.CustomAttributes.Add(new CodeAttributeDeclaration("System.Diagnostics.CodeAnalysis.AllowNullAttribute"));
11301131
member.CustomAttributes.Add(new CodeAttributeDeclaration("System.Diagnostics.CodeAnalysis.MaybeNullAttribute"));

0 commit comments

Comments
 (0)