Skip to content

Commit

Permalink
Merge pull request #188 from Etogy/class-visitor
Browse files Browse the repository at this point in the history
Added an optional TypeVisitor delegate
  • Loading branch information
mganss authored Apr 30, 2020
2 parents 9ad47b4 + 19cd727 commit 8fc1bea
Show file tree
Hide file tree
Showing 4 changed files with 212 additions and 0 deletions.
194 changes: 194 additions & 0 deletions XmlSchemaClassGenerator.Tests/VisitorTests.cs
Original file line number Diff line number Diff line change
@@ -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<string> 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 = @"<?xml version=""1.0"" encoding = ""UTF-8""?>
<xs:schema elementFormDefault=""qualified"" xmlns:xs=""http://www.w3.org/2001/XMLSchema"" targetNamespace=""http://local.none"">
<xs:complexType name=""MyType"">
<xs:sequence>
<xs:element maxOccurs=""1"" minOccurs=""0"" name=""output"" type=""xs:string""/>
</xs:sequence>
</xs:complexType>
</xs:schema>
";

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 = @"<?xml version=""1.0"" encoding = ""UTF-8""?>
<xs:schema elementFormDefault=""qualified"" xmlns:xs=""http://www.w3.org/2001/XMLSchema"" targetNamespace=""http://local.none"">
<xs:complexType name=""MyType"">
<xs:sequence>
<xs:element maxOccurs=""1"" minOccurs=""0"" name=""output"" type=""xs:int""/>
</xs:sequence>
</xs:complexType>
</xs:schema>
";

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 = @"<?xml version=""1.0"" encoding = ""UTF-8""?>
<xs:schema elementFormDefault=""qualified"" xmlns:xs=""http://www.w3.org/2001/XMLSchema"" targetNamespace=""http://local.none"">
<xs:complexType name=""MyType"">
<xs:simpleContent>
<xs:extension base=""xs:string"">
<xs:attribute name=""myAttribute"" type=""xs:string""/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:schema>
";

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 = @"<?xml version=""1.0"" encoding = ""UTF-8""?>
<xs:schema elementFormDefault=""qualified"" xmlns:xs=""http://www.w3.org/2001/XMLSchema"" targetNamespace=""http://local.none"">
<xs:complexType name=""MyType"">
<xs:sequence>
<xs:element maxOccurs=""1"" minOccurs=""0"" name=""output"" type=""xs:string""/>
</xs:sequence>
</xs:complexType>
</xs:schema>
";

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 = @"<?xml version=""1.0"" encoding = ""UTF-8""?>
<xs:schema elementFormDefault=""qualified"" xmlns:xs=""http://www.w3.org/2001/XMLSchema"" targetNamespace=""http://local.none"">
<xs:simpleType name=""MyType"">
<xs:restriction base=""xs:string"">
<xs:enumeration value=""One""/>
<xs:enumeration value=""Two""/>
<xs:enumeration value=""Three""/>
</xs:restriction>
</xs:simpleType>
</xs:schema>
";

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);
}
}
}
9 changes: 9 additions & 0 deletions XmlSchemaClassGenerator/Generator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,15 @@ public Action<CodeTypeMember, PropertyModel> MemberVisitor
set { _configuration.MemberVisitor = value; }
}

/// <summary>
/// Optional delegate that is called for each generated type (class, interface, enum)
/// </summary>
public Action<CodeTypeDeclaration, TypeModel> TypeVisitor
{
get { return _configuration.TypeVisitor; }
set { _configuration.TypeVisitor = value; }
}

public VersionProvider Version
{
get { return _configuration.Version; }
Expand Down
6 changes: 6 additions & 0 deletions XmlSchemaClassGenerator/GeneratorConfiguration.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -193,6 +194,11 @@ public void WriteLog(string message)
/// </summary>
public Action<CodeTypeMember, PropertyModel> MemberVisitor { get; set; }

/// <summary>
/// Optional delegate that is called for each generated type (class, interface, enum)
/// </summary>
public Action<CodeTypeDeclaration, TypeModel> TypeVisitor { get; set; }

/// <summary>
/// Provides options to customize Elementnamens with own logik
/// </summary>
Expand Down
3 changes: 3 additions & 0 deletions XmlSchemaClassGenerator/TypeModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,7 @@ public override CodeTypeDeclaration Generate()

interfaceDeclaration.BaseTypes.AddRange(Interfaces.Select(i => i.GetReferenceFor(Namespace)).ToArray());

Configuration.TypeVisitor(interfaceDeclaration, this);
return interfaceDeclaration;
}
}
Expand Down Expand Up @@ -473,6 +474,7 @@ public override CodeTypeDeclaration Generate()

classDeclaration.BaseTypes.AddRange(Interfaces.Select(i => i.GetReferenceFor(Namespace)).ToArray());

Configuration.TypeVisitor(classDeclaration, this);
return classDeclaration;
}

Expand Down Expand Up @@ -1249,6 +1251,7 @@ public override CodeTypeDeclaration Generate()
enumDeclaration.Members.Add(member);
}

Configuration.TypeVisitor(enumDeclaration, this);
return enumDeclaration;
}

Expand Down

0 comments on commit 8fc1bea

Please sign in to comment.