Skip to content

Commit

Permalink
Applied serializer type check using WithUnknownContent (#492)
Browse files Browse the repository at this point in the history
  • Loading branch information
Mike-E-angelo authored Dec 7, 2020
1 parent 5e5c10c commit 90345c7
Show file tree
Hide file tree
Showing 6 changed files with 130 additions and 10 deletions.
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using ExtendedXmlSerializer.ContentModel.Content;
using ExtendedXmlSerializer.Core.Sources;

namespace ExtendedXmlSerializer.ContentModel.Members
Expand All @@ -6,5 +7,7 @@ sealed class FixedInstanceMemberSerialization
: FixedInstanceSource<object, IMemberSerialization>, IInstanceMemberSerialization
{
public FixedInstanceMemberSerialization(IMemberSerialization instance) : base(instance) {}

public IMemberSerialization Get(IInnerContent parameter) => Get(parameter.Current);
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
using ExtendedXmlSerializer.ContentModel.Content;
using ExtendedXmlSerializer.Core.Sources;

namespace ExtendedXmlSerializer.ContentModel.Members
{
interface IInstanceMemberSerialization : IParameterizedSource<object, IMemberSerialization> {}
interface IInstanceMemberSerialization : IParameterizedSource<IInnerContent, IMemberSerialization>,
IParameterizedSource<object, IMemberSerialization> {}
}
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using ExtendedXmlSerializer.ContentModel.Content;
using ExtendedXmlSerializer.ContentModel.Reflection;
using ExtendedXmlSerializer.Core.Specifications;
using ExtendedXmlSerializer.ExtensionModel.Types;
Expand All @@ -22,11 +23,14 @@ public InstanceMemberSerialization(ISpecification<TypeInfo> specification, IMemb
_serialization = serialization;
}

public IMemberSerialization Get(IInnerContent parameter) => Get(parameter.Current);

public IMemberSerialization Get(object parameter)
{
var type = parameter is ITypeAware aware ? aware.Get() : parameter.GetType().GetTypeInfo();
var result = _specification.IsSatisfiedBy(type) ? _serializations.Get(type) : _serialization;
return result;
}

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,17 +19,21 @@ public MemberInnerContentHandler(IInstanceMemberSerialization serialization, IMe

public bool IsSatisfiedBy(IInnerContent parameter)
{
var content = parameter.Get();
var key = _formatter.Get(content);
var memberSerialization = _serialization.Get(parameter.Current);
var member = memberSerialization.Get(key);
var result = member != null;
if (result)
var content = parameter.Get();
var key = _formatter.Get(content);
var serialization = _serialization.Get(parameter);
if (serialization != null)
{
_handler.Handle(parameter, member);
var member = serialization.Get(key);
var result = member != null;
if (result)
{
_handler.Handle(parameter, member);
return true;
}
}

return result;
return false;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,53 @@ sealed class UnknownContentHandlingExtension : ISerializerExtension

public IServiceRepository Get(IServiceRepository parameter)
=> parameter.RegisterInstance(_action)
.Decorate<IInnerContentServices, Services>();
.Decorate<IInnerContentServices, Services>()
.Decorate<IInstanceMemberSerializations, InstanceMemberSerializations>();

void ICommand<IServices>.Execute(IServices parameter) {}

sealed class InstanceMemberSerializations : IInstanceMemberSerializations
{
readonly IInstanceMemberSerializations _previous;
readonly IInnerContentServices _services;

public InstanceMemberSerializations(IInstanceMemberSerializations previous, IInnerContentServices services)
{
_previous = previous;
_services = services;
}

public IInstanceMemberSerialization Get(TypeInfo parameter)
=> new InstanceMemberSerialization(_previous.Get(parameter), _services);

sealed class InstanceMemberSerialization : IInstanceMemberSerialization
{
readonly IInstanceMemberSerialization _previous;
readonly IInnerContentServices _services;

public InstanceMemberSerialization(IInstanceMemberSerialization previous,
IInnerContentServices services)
{
_previous = previous;
_services = services;
}

public IMemberSerialization Get(IInnerContent parameter)
{
var content = parameter.Get();
var key = _services.Get(content);
var serialization = _previous.Get(parameter);
var serializer = serialization.Get(key);
var result = serializer is PropertyMemberSerializer && !content.IsSatisfiedBy(serializer.Profile)
? null
: serialization;
return result;
}

public IMemberSerialization Get(object parameter) => _previous.Get(parameter);
}
}

sealed class Services : IInnerContentServices
{
readonly IInnerContentServices _services;
Expand Down
64 changes: 64 additions & 0 deletions test/ExtendedXmlSerializer.Tests.ReportedIssues/Issue491Tests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
using ExtendedXmlSerializer.Configuration;
using FluentAssertions;
using System.Xml.Serialization;
using Xunit;

namespace ExtendedXmlSerializer.Tests.ReportedIssues
{
public sealed class Issue491Tests
{
[Fact]
public void Test()
{
var serializer = new ConfigurationContainer().WithUnknownContent().Continue().Create();

// Create an object which have its Id as element
var obj2 = new RootObjectIdElement() {Id = 2, Name = "RootObjectId 2"};
var text2 = serializer.Serialize(obj2);
//_output.WriteLine(text2);
// <?xml version="1.0" encoding="utf-8"?><BugAttributeInsteadOfElement-RootObjectIdElement xmlns="clr-namespace:Test.XmlSerializer;assembly=Test"><Id>2</Id><Name>RootObjectId 2</Name></BugAttributeInsteadOfElement-RootObjectIdElement>

// TEST 1: Change object types which allows deserialize type
var bugText1 = text2.Replace("RootObjectIdElement", "RootObjectIdAttribute");
var bugObj1 = serializer.Deserialize<RootObjectIdAttribute>(bugText1);
// RESULT 1: BUG encountered! Name is null although WithUnknownContent().Continue() is enabled
bugObj1.Name.Should().Be("RootObjectId 2");
bugObj1.Id.Should().Be(0);

// TEST 2: Set Id as Attribute and parallel as unknown element
var bugText2 = bugText1.Replace("-RootObjectIdAttribute ", @"-RootObjectIdAttribute Id=""1"" ");
var bugObj2 = serializer.Deserialize<RootObjectIdAttribute>(bugText2);
// RESULT 2: BUG also exists in case the attribute is set too
bugObj2.Name.Should().Be("RootObjectId 2");
bugObj2.Id.Should().Be(1);




// TEST 3: Rename element Id to Id2 - therefore it has not the same name as expected attribute
var bugText3 = bugText1.Replace("<Id>", "<Id2>").Replace("</Id>", "</Id2>");
var bugObj3 = serializer.Deserialize<RootObjectIdAttribute>(bugText3);
// RESULT 3: Works just fine
bugObj3.Name.Should().NotBeNull();
bugObj3.Id.Should().Be(0);

// => BUG happens only if an unknown content is determined which has same name as an expected attribute!
}

public class RootObjectIdAttribute
{
[XmlAttribute]
public int Id { get; set; }

public string Name { get; set; }
}

public class RootObjectIdElement
{
public int Id { get; set; }

public string Name { get; set; }
}

}
}

0 comments on commit 90345c7

Please sign in to comment.