Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
using System;
using ExtendedXmlSerializer.Core.Sources;
using System;

namespace ExtendedXmlSerializer.ContentModel.Identification
{
sealed class IdentityStore : Cache<string, Func<string, IIdentity>>, IIdentityStore
{
public IdentityStore() : base(i => new Names(i).Get) {}

public IIdentity Get(string name, string identifier) => Get(identifier)
.Invoke(name);
public IIdentity Get(string name, string identifier) => Get(identifier).Invoke(name);

sealed class Names : CacheBase<string, IIdentity>
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,56 +1,63 @@
using System;
using System.Collections.Immutable;
using System.Reflection;
using ExtendedXmlSerializer.ContentModel.Conversion;
using ExtendedXmlSerializer.ContentModel.Identification;
using ExtendedXmlSerializer.Core.Sources;
using Sprache;
using System;
using System.Collections.Immutable;
using System.Reflection;

namespace ExtendedXmlSerializer.ContentModel.Reflection
namespace ExtendedXmlSerializer.ContentModel.Reflection;

sealed class TypePartReflector : CacheBase<TypeParts, TypeInfo>, ITypePartReflector
{
sealed class TypePartReflector : CacheBase<TypeParts, TypeInfo>, ITypePartReflector
readonly IIdentityStore _identities;
readonly ITypes _types;

public TypePartReflector(IIdentityStore identities, ITypes types) : base(TypePartsEqualityComparer.Default)
{
readonly IIdentityStore _identities;
readonly ITypes _types;
_identities = identities;
_types = types;
}

public TypePartReflector(IIdentityStore identities, ITypes types) : base(TypePartsEqualityComparer.Default)
{
_identities = identities;
_types = types;
}
protected override TypeInfo Create(TypeParts parameter)
{
var identity = _identities.Get(parameter.Name, parameter.Identifier);
var typeInfo = _types.Get(identity);
var arguments = parameter.GetArguments();
var type = (arguments.HasValue ? Generic(typeInfo, arguments.Value) : typeInfo)
??
throw new
ParseException($"An attempt was made to parse the identity '{IdentityFormatter.Default.Get(identity)}', but no type could be located with that name.");
var result = parameter.Dimensions.HasValue
? new DimensionsAlteration(parameter.Dimensions.Value).Get(type)
: type;
return result;
}

protected override TypeInfo Create(TypeParts parameter)
{
var identity = _identities.Get(parameter.Name, parameter.Identifier);
var typeInfo = _types.Get(identity);
var arguments = parameter.GetArguments();
var type = arguments.HasValue
? typeInfo.MakeGenericType(Arguments(arguments.Value))
.GetTypeInfo()
: typeInfo;
if (type == null)
{
throw new ParseException(
$"An attempt was made to parse the identity '{IdentityFormatter.Default.Get(identity)}', but no type could be located with that name.");
}

var result = parameter.Dimensions.HasValue
? new DimensionsAlteration(parameter.Dimensions.Value).Get(type)
: type;
return result;
}
TypeInfo Generic(TypeInfo candidate, ImmutableArray<TypeParts> arguments)
{
var definition = candidate.Name.EndsWith($"`{arguments.Length}")
? candidate
: Locate(candidate, arguments.Length);
return definition.MakeGenericType(Arguments(arguments)).GetTypeInfo();
}

Type[] Arguments(ImmutableArray<TypeParts> names)
static Type Locate(TypeInfo candidate, int count)
{
var original = candidate.FullName;
var name = $"{original.Split('`')[0]}`{count}";
return candidate.Assembly.GetType(name, true);
}

Type[] Arguments(ImmutableArray<TypeParts> names)
{
var length = names.Length;
var result = new Type[length];
for (var i = 0; i < length; i++)
{
var length = names.Length;
var result = new Type[length];
for (var i = 0; i < length; i++)
{
result[i] = Get(names[i])
.AsType();
}

return result;
result[i] = Get(names[i]);
}

return result;
}
}
3 changes: 1 addition & 2 deletions src/ExtendedXmlSerializer/ContentModel/Reflection/Types.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ sealed class Types : CacheBase<IIdentity, TypeInfo>, ITypes
readonly ITypeIdentities _aliased;
readonly ITypeCandidates _candidates;


// ReSharper disable once TooManyDependencies
[UsedImplicitly]
public Types(IPartitionedTypeSpecification specification, IAssemblyTypePartitions partitions,
Expand All @@ -25,6 +24,6 @@ public Types(IPartitionedTypeSpecification specification, IAssemblyTypePartition
}

protected override TypeInfo Create(IIdentity parameter)
=> _aliased.Get(parameter) ?? _candidates.Get(parameter).SingleOrDefault();
=> _aliased.Get(parameter) ?? _candidates.Get(parameter).FirstOrDefault();
}
}
60 changes: 60 additions & 0 deletions test/ExtendedXmlSerializer.Tests.ReportedIssues/Issue644Tests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
using ExtendedXmlSerializer.Configuration;
using ExtendedXmlSerializer.Tests.ReportedIssues.Support;
using FluentAssertions;
using Xunit;

namespace ExtendedXmlSerializer.Tests.ReportedIssues;

public sealed class Issue644Tests
{
[Fact]
public void VerifySingle()
{
var sut = new ConfigurationContainer().EnableAllConstructors()
.UseAutoFormatting()
.EnableClassicListNaming()
.UseOptimizedNamespaces()
.AllowMultipleReferences()
.EnableXmlText()
.Create()
.ForTesting();
var instance = new ObjectContainer
{
Object = new IssueClass<int> { value = 2 }
};
sut.Cycle(instance).Should().BeEquivalentTo(instance);
}

[Fact]
public void VerifyDouble()
{
var sut = new ConfigurationContainer().EnableAllConstructors()
.UseAutoFormatting()
.EnableClassicListNaming()
.UseOptimizedNamespaces()
.AllowMultipleReferences()
.EnableXmlText()
.Create()
.ForTesting();
var instance = new ObjectContainer
{
Object = new IssueClass<int, string> { value = 2, other = "Hello world!" }
};
sut.Cycle(instance).Should().BeEquivalentTo(instance);
}

public class ObjectContainer
{
public object Object { get; set; }
}

public class IssueClass<T>
{
public T value;
}

public class IssueClass<T, U> : IssueClass<T>
{
public U other;
}
}
35 changes: 35 additions & 0 deletions test/ExtendedXmlSerializer.Tests.ReportedIssues/Issue645Tests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
using ExtendedXmlSerializer.Configuration;
using ExtendedXmlSerializer.Tests.ReportedIssues.Support;
using FluentAssertions;
using System;
using System.Runtime.CompilerServices;
using Xunit;

namespace ExtendedXmlSerializer.Tests.ReportedIssues
{
public sealed class Issue645Tests
{

#if CORE
[Fact]
public void VerifyTupleContainer()
{
var sut = new ConfigurationContainer().EnableParameterizedContent().Create().ForTesting();
var instance = new TupleContainer { Subject = Tuple.Create(123) };
sut.Cycle(instance).Should().BeEquivalentTo(instance);
}

public class TupleContainer
{
public ITuple Subject { get; set; }
}
#endif
[Fact]
public void VerifyTuple()
{
var sut = new ConfigurationContainer().EnableParameterizedContent().Create().ForTesting();
var instance = Tuple.Create(123);
sut.Cycle(instance).Should().BeEquivalentTo(instance);
}
}
}