From 9446f5129827311a2cbe53825dc0d2f9951924eb Mon Sep 17 00:00:00 2001 From: Ben Callaghan Date: Mon, 27 Apr 2020 13:25:04 -0600 Subject: [PATCH 1/2] Added an optional TypeVisitor delegate --- XmlSchemaClassGenerator/Generator.cs | 9 +++++++++ XmlSchemaClassGenerator/GeneratorConfiguration.cs | 6 ++++++ XmlSchemaClassGenerator/TypeModel.cs | 3 +++ 3 files changed, 18 insertions(+) diff --git a/XmlSchemaClassGenerator/Generator.cs b/XmlSchemaClassGenerator/Generator.cs index 1ece78d4..7b2b3607 100644 --- a/XmlSchemaClassGenerator/Generator.cs +++ b/XmlSchemaClassGenerator/Generator.cs @@ -195,6 +195,15 @@ public Action MemberVisitor set { _configuration.MemberVisitor = value; } } + /// + /// Optional delegate that is called for each generated type (class, interface, enum) + /// + public Action TypeVisitor + { + get { return _configuration.TypeVisitor; } + set { _configuration.TypeVisitor = value; } + } + public VersionProvider Version { get { return _configuration.Version; } diff --git a/XmlSchemaClassGenerator/GeneratorConfiguration.cs b/XmlSchemaClassGenerator/GeneratorConfiguration.cs index 2e81715e..88ed1b10 100644 --- a/XmlSchemaClassGenerator/GeneratorConfiguration.cs +++ b/XmlSchemaClassGenerator/GeneratorConfiguration.cs @@ -33,6 +33,7 @@ public GeneratorConfiguration() GenerateSerializableAttribute = GenerateDesignerCategoryAttribute = true; CollectionType = typeof(Collection<>); MemberVisitor = (member, model) => { }; + TypeVisitor = (type, model) => { }; NamingProvider = new NamingProvider(NamingScheme); Version = VersionProvider.CreateFromAssembly(); EnableUpaCheck = true; @@ -185,6 +186,11 @@ public void WriteLog(string message) /// public Action MemberVisitor { get; set; } + /// + /// Optional delegate that is called for each generated type (class, interface, enum) + /// + public Action TypeVisitor { get; set; } + /// /// Provides options to customize Elementnamens with own logik /// diff --git a/XmlSchemaClassGenerator/TypeModel.cs b/XmlSchemaClassGenerator/TypeModel.cs index d66a8470..b082646c 100644 --- a/XmlSchemaClassGenerator/TypeModel.cs +++ b/XmlSchemaClassGenerator/TypeModel.cs @@ -222,6 +222,7 @@ public override CodeTypeDeclaration Generate() interfaceDeclaration.BaseTypes.AddRange(Interfaces.Select(i => i.GetReferenceFor(Namespace)).ToArray()); + Configuration.TypeVisitor(interfaceDeclaration, this); return interfaceDeclaration; } } @@ -473,6 +474,7 @@ public override CodeTypeDeclaration Generate() classDeclaration.BaseTypes.AddRange(Interfaces.Select(i => i.GetReferenceFor(Namespace)).ToArray()); + Configuration.TypeVisitor(classDeclaration, this); return classDeclaration; } @@ -1249,6 +1251,7 @@ public override CodeTypeDeclaration Generate() enumDeclaration.Members.Add(member); } + Configuration.TypeVisitor(enumDeclaration, this); return enumDeclaration; } From 19cd7276d68d377856380dfba51a5b598a7b2d39 Mon Sep 17 00:00:00 2001 From: Ben Callaghan Date: Wed, 29 Apr 2020 12:12:07 -0600 Subject: [PATCH 2/2] Added tests for visitor callbacks --- XmlSchemaClassGenerator.Tests/VisitorTests.cs | 194 ++++++++++++++++++ 1 file changed, 194 insertions(+) create mode 100644 XmlSchemaClassGenerator.Tests/VisitorTests.cs diff --git a/XmlSchemaClassGenerator.Tests/VisitorTests.cs b/XmlSchemaClassGenerator.Tests/VisitorTests.cs new file mode 100644 index 00000000..c252f24e --- /dev/null +++ b/XmlSchemaClassGenerator.Tests/VisitorTests.cs @@ -0,0 +1,194 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Xml.Schema; +using Xunit; + +namespace XmlSchemaClassGenerator.Tests { + public class VisitorTests + { + private IEnumerable ConvertXml(string name, string xsd, Generator generatorPrototype = null) + { + if (name is null) + { + throw new ArgumentNullException(nameof(name)); + } + + var writer = new MemoryOutputWriter(); + + var gen = new Generator + { + OutputWriter = writer, + Version = new VersionProvider("Tests", "1.0.0.1"), + NamespaceProvider = generatorPrototype.NamespaceProvider, + GenerateNullables = generatorPrototype.GenerateNullables, + IntegerDataType = generatorPrototype.IntegerDataType, + DataAnnotationMode = generatorPrototype.DataAnnotationMode, + GenerateDesignerCategoryAttribute = generatorPrototype.GenerateDesignerCategoryAttribute, + GenerateComplexTypesForCollections = generatorPrototype.GenerateComplexTypesForCollections, + EntityFramework = generatorPrototype.EntityFramework, + AssemblyVisible = generatorPrototype.AssemblyVisible, + GenerateInterfaces = generatorPrototype.GenerateInterfaces, + MemberVisitor = generatorPrototype.MemberVisitor, + TypeVisitor = generatorPrototype.TypeVisitor, + CodeTypeReferenceOptions = generatorPrototype.CodeTypeReferenceOptions + }; + + var set = new XmlSchemaSet(); + + using (var stringReader = new StringReader(xsd)) + { + var schema = XmlSchema.Read(stringReader, (s, e) => + { + throw new InvalidOperationException($"{e.Severity}: {e.Message}",e.Exception); + }); + + set.Add(schema); + } + + gen.Generate(set); + + return writer.Content; + } + + [Fact] + public void MemberVisitorIsCalledForProperty() + { + const string xsd = @" + + + + + + + +"; + + var memberVisitorWasCalled = false; + var generatedType = ConvertXml(nameof(MemberVisitorIsCalledForProperty), xsd, new Generator + { + NamespaceProvider = new NamespaceProvider + { + GenerateNamespace = key => "Test" + }, + MemberVisitor = (member, model) => memberVisitorWasCalled = true + }); + + Assert.True(memberVisitorWasCalled); + } + + [Fact] + public void MemberVisitorIsCalledForAllNullableProperties() + { + const string xsd = @" + + + + + + + +"; + + var visitorCount = 0; + var generatedType = ConvertXml(nameof(MemberVisitorIsCalledForProperty), xsd, new Generator + { + NamespaceProvider = new NamespaceProvider + { + GenerateNamespace = key => "Test" + }, + GenerateNullables = true, + MemberVisitor = (member, model) => visitorCount++ + }); + + // Visitor should be called 3 times: Value, ValueSpecified, and Nullable + Assert.Equal(3, visitorCount); + } + + [Fact] + public void MemberVisitorIsCalledForTextContent() + { + const string xsd = @" + + + + + + + + + +"; + + var visitorCount = 0; + var generatedType = ConvertXml(nameof(MemberVisitorIsCalledForProperty), xsd, new Generator + { + NamespaceProvider = new NamespaceProvider + { + GenerateNamespace = key => "Test" + }, + GenerateNullables = true, + MemberVisitor = (member, model) => visitorCount++ + }); + + // Visitor should be called 2 times: Value and MyAttribute + Assert.Equal(2, visitorCount); + } + + [Fact] + public void TypeVisitorIsCalledForClass() + { + const string xsd = @" + + + + + + + +"; + + var typeVisitorWasCalled = false; + var generatedType = ConvertXml(nameof(MemberVisitorIsCalledForProperty), xsd, new Generator + { + NamespaceProvider = new NamespaceProvider + { + GenerateNamespace = key => "Test" + }, + TypeVisitor = (type, model) => typeVisitorWasCalled = true + }); + + Assert.True(typeVisitorWasCalled); + } + + [Fact] + public void TypeVisitorIsCalledForEnum() + { + const string xsd = @" + + + + + + + + + +"; + + var typeVisitorWasCalled = false; + var generatedType = ConvertXml(nameof(MemberVisitorIsCalledForProperty), xsd, new Generator + { + NamespaceProvider = new NamespaceProvider + { + GenerateNamespace = key => "Test" + }, + TypeVisitor = (type, model) => typeVisitorWasCalled = true + }); + + Assert.True(typeVisitorWasCalled); + } + } +}