Skip to content

Commit 86c6018

Browse files
authored
Merge pull request #7 from rafek1241/feature/#2-base-type-namespace-inclusion
Feature/#2 base type namespace inclusion
2 parents 435c9b4 + 7d4ca6f commit 86c6018

File tree

4 files changed

+132
-29
lines changed

4 files changed

+132
-29
lines changed

src/ReBus.Serializer.XML/XmlSerializer.cs

Lines changed: 66 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
using Newtonsoft.Json.Converters;
1111
using Newtonsoft.Json.Linq;
1212
using Rebus.Bus;
13+
using Rebus.Extensions;
1314
using Rebus.Messages;
1415
using Rebus.Serialization;
1516
using ReBus.Serializer.XML.Exceptions;
@@ -41,34 +42,85 @@ public XmlSerializer(XmlSerializingOptions options)
4142

4243
public Task<TransportMessage> Serialize(Message message)
4344
{
44-
var messageType = Type.GetType(message.GetMessageType());
45-
4645
using var ms = new MemoryStream();
4746
using var xmlWriter = new XmlTextWriter(ms, _options.Encoding);
4847

48+
var messageType = Type.GetType(message.GetMessageType());
49+
ComposeXmlMessage(message, xmlWriter, messageType);
50+
xmlWriter.Flush();
51+
52+
var result = Encoding.ASCII.GetString(ms.ToArray());
53+
_logger?.LogDebug("Serialized '{Type}' message to XML content: {Result}", messageType?.Name, result);
54+
55+
return Task.FromResult(new TransportMessage(message.Headers, ms.ToArray()));
56+
}
57+
58+
private void ComposeXmlMessage(
59+
Message message,
60+
XmlTextWriter xmlWriter,
61+
Type messageType
62+
)
63+
{
4964
xmlWriter.WriteStartDocument();
50-
51-
var namespaceOfMessage = DefineNamespaceOfMessage(message, messageType);
52-
xmlWriter.WriteStartElement(_options.RootName, namespaceOfMessage);
5365

54-
xmlWriter.WriteAttributeString("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance");
55-
xmlWriter.WriteAttributeString("xmlns:xsd", "http://www.w3.org/2001/XMLSchema");
56-
66+
WriteRootContainerElement(message, xmlWriter, messageType);
67+
SerializeAndWriteXmlMessage(message, xmlWriter, messageType);
68+
69+
xmlWriter.WriteEndDocument();
70+
}
71+
72+
private void SerializeAndWriteXmlMessage(
73+
Message message,
74+
XmlTextWriter xmlWriter,
75+
Type messageType
76+
)
77+
{
5778
var messageBody = JsonConvert.SerializeObject(message.Body, _jsonSettings);
5879
var xmlObj = JsonConvert.DeserializeXmlNode(
5980
messageBody,
6081
messageType?.Name ?? throw new InvalidOperationException()
6182
);
62-
83+
6384
xmlWriter.WriteRaw(xmlObj.InnerXml);
85+
}
6486

65-
xmlWriter.WriteEndDocument();
66-
xmlWriter.Flush();
87+
private void WriteRootContainerElement(
88+
Message message,
89+
XmlTextWriter xmlWriter,
90+
Type messageType
91+
)
92+
{
93+
var namespaceOfMessage = DefineNamespaceOfMessage(message, messageType);
94+
xmlWriter.WriteStartElement(_options.RootName, namespaceOfMessage);
6795

68-
var result = Encoding.ASCII.GetString(ms.ToArray());
69-
_logger?.LogDebug("Serialized '{Type}' message to XML content: {Result}", messageType.Name, result);
96+
if (_options.IncludeBaseTypeNamespaces)
97+
{
98+
IncludeBaseTypesInElement(xmlWriter, messageType);
99+
}
70100

71-
return Task.FromResult(new TransportMessage(message.Headers, ms.ToArray()));
101+
xmlWriter.WriteAttributeString("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance");
102+
xmlWriter.WriteAttributeString("xmlns:xsd", "http://www.w3.org/2001/XMLSchema");
103+
}
104+
105+
private void IncludeBaseTypesInElement(XmlTextWriter xmlWriter, Type messageType)
106+
{
107+
var baseTypes = messageType
108+
.GetBaseTypes()
109+
.Where(x => x != typeof(object))
110+
.ToArray();
111+
112+
var firstBaseType = baseTypes.FirstOrDefault();
113+
if (firstBaseType == null)
114+
{
115+
return;
116+
}
117+
118+
xmlWriter.WriteAttributeString($"xmlns:{_options.BaseTypeNamespaceAttributeName}", firstBaseType.FullName!);
119+
120+
for (var i = 1; i < baseTypes.Length; i++)
121+
{
122+
xmlWriter.WriteAttributeString($"xmlns:{_options.BaseTypeNamespaceAttributeName}{i}", baseTypes[i].FullName!);
123+
}
72124
}
73125

74126
private string DefineNamespaceOfMessage(Message message, Type messageType)

src/ReBus.Serializer.XML/XmlSerializingOptions.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,10 @@ namespace ReBus.Serializer.XML
55
public class XmlSerializingOptions
66
{
77
public string RootName { get; set; } = "Messages";
8-
public bool IncludeNamespace { get; set; }
8+
public bool IncludeNamespace { get; set; } = true;
9+
public bool IncludeBaseTypeNamespaces { get; set; } = true;
910
public string DefaultNamespacePrefix { get; set; } = "http://tempuri.org";
10-
11+
public string BaseTypeNamespaceAttributeName { get; set; } = "baseType";
1112
public Encoding Encoding { get; set; } = null;
1213
}
1314
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
namespace ReBus.Serializer.XML.UnitTests.Messages.BaseTypes
2+
{
3+
internal class RootClass
4+
{
5+
public string RootProp { get; set; }
6+
}
7+
8+
internal class SubClass : RootClass
9+
{
10+
public string SubClassProp { get; set; }
11+
}
12+
13+
internal interface IAmImplementedInterface
14+
{
15+
}
16+
17+
internal class TestMessageWithBaseTypes : SubClass, IAmImplementedInterface
18+
{
19+
public string Prop { get; set; }
20+
}
21+
}

tests/ReBus.Serializer.XML.UnitTests/XmlSerializerTests.cs

Lines changed: 42 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,12 @@
44
using System.Threading.Tasks;
55
using AutoFixture;
66
using FluentAssertions;
7+
using Microsoft.Extensions.Logging;
78
using Microsoft.Extensions.Logging.Xunit;
89
using Newtonsoft.Json;
910
using Rebus.Messages;
1011
using ReBus.Serializer.XML.UnitTests.Messages;
12+
using ReBus.Serializer.XML.UnitTests.Messages.BaseTypes;
1113
using Xunit;
1214
using Xunit.Abstractions;
1315

@@ -16,32 +18,39 @@ namespace ReBus.Serializer.XML.UnitTests
1618
public class XmlSerializerTests
1719
{
1820
private readonly Fixture _fixture;
19-
private readonly XmlSerializer _sut;
21+
private XmlSerializer Sut
22+
{
23+
get
24+
{
25+
var serializer = new XmlSerializer(_options);
26+
serializer.WithLogging(_logger);
27+
return serializer;
28+
}
29+
}
2030

21-
private readonly XmlSerializingOptions _options;
31+
private XmlSerializingOptions _options;
32+
private readonly ILogger _logger;
2233

2334
public XmlSerializerTests(ITestOutputHelper outputHelper)
2435
{
2536
_fixture = new Fixture();
26-
_options = new XmlSerializingOptions()
27-
{
28-
IncludeNamespace = true
29-
};
30-
31-
var logger = new XunitLoggerProvider(outputHelper)
37+
_options = new XmlSerializingOptions();
38+
_logger = new XunitLoggerProvider(outputHelper)
3239
.CreateLogger(nameof(XmlSerializerTests));
3340

34-
_sut = new XmlSerializer(_options);
35-
_sut.WithLogging(logger);
3641
}
3742

3843
[Fact]
3944
public async Task when_message_passed_with_protected_setters__maps_that_to_proper_xml()
4045
{
4146
var testMessage = _fixture.Create<TestMessageWithProtectedSetters>();
4247
var message = new Message(new Dictionary<string, string>(), testMessage);
43-
44-
var transportMessage = await _sut
48+
_options = new XmlSerializingOptions()
49+
{
50+
IncludeBaseTypeNamespaces = false
51+
};
52+
53+
var transportMessage = await Sut
4554
.Serialize(message)
4655
.ConfigureAwait(false);
4756

@@ -62,6 +71,26 @@ public async Task when_message_passed_with_protected_setters__maps_that_to_prope
6271
);
6372
}
6473

74+
[Fact]
75+
public async Task when_passed_message_with_base_types__maps_to_xml_object_with_base_types_in_root_container()
76+
{
77+
var testMessage = _fixture.Create<TestMessageWithBaseTypes>();
78+
var message = new Message(new Dictionary<string, string>(), testMessage);
79+
_options = new XmlSerializingOptions();
80+
81+
var transportMessage = await Sut
82+
.Serialize(message)
83+
.ConfigureAwait(false);
84+
85+
var result = transportMessage.Body;
86+
var resultAsString = Encoding.UTF8.GetString(result);
87+
88+
resultAsString.Should()
89+
.Contain(
90+
"xmlns:baseType=\"ReBus.Serializer.XML.UnitTests.Messages.BaseTypes.IAmImplementedInterface\" xmlns:baseType1=\"ReBus.Serializer.XML.UnitTests.Messages.BaseTypes.SubClass\" xmlns:baseType2=\"ReBus.Serializer.XML.UnitTests.Messages.BaseTypes.RootClass\""
91+
);
92+
}
93+
6594
[Fact]
6695
public async Task when_transport_message_passed_with_specified_type__maps_to_specific_object()
6796
{
@@ -83,7 +112,7 @@ public async Task when_transport_message_passed_with_specified_type__maps_to_spe
83112
};
84113
var message = new TransportMessage(headers, Encoding.Default.GetBytes(input));
85114

86-
var result = await _sut
115+
var result = await Sut
87116
.Deserialize(message)
88117
.ConfigureAwait(false);
89118

0 commit comments

Comments
 (0)