Skip to content

Commit

Permalink
Merge 18b6d34 into f5a749a
Browse files Browse the repository at this point in the history
  • Loading branch information
Mike-E-angelo authored Jul 6, 2020
2 parents f5a749a + 18b6d34 commit 0752564
Show file tree
Hide file tree
Showing 7 changed files with 210 additions and 38 deletions.
Original file line number Diff line number Diff line change
@@ -1,18 +1,29 @@
using ExtendedXmlSerializer.Core.Sources;
using System.Collections.Generic;
using System.Reflection;
using ExtendedXmlSerializer.Core.Sources;

namespace ExtendedXmlSerializer.ContentModel.Members
{
sealed class MappedAllowedMemberValues
: TableSource<MemberInfo, IAllowedValueSpecification>,
IAllowedMemberValues
sealed class MappedAllowedMemberValues : IAllowedMemberValues
{
public MappedAllowedMemberValues(IDictionary<MemberInfo, IAllowedValueSpecification> store) : base(store) {}
readonly Table _primary;

public MappedAllowedMemberValues(IDictionary<MemberInfo, IAllowedValueSpecification> primary)
: this(new Table(new TableSource<MemberInfo, IAllowedValueSpecification>(primary))) {}

MappedAllowedMemberValues(Table primary) => _primary = primary;

public IAllowedValueSpecification Get(MemberInfo parameter)
=> _primary.Get(parameter);

sealed class Table : IParameterizedSource<MemberDescriptor, IAllowedValueSpecification>
{
readonly IParameterizedSource<MemberInfo, IAllowedValueSpecification> _source;

public override IAllowedValueSpecification Get(MemberInfo parameter) => From(parameter);
public Table(IParameterizedSource<MemberInfo, IAllowedValueSpecification> source) => _source = source;

IAllowedValueSpecification From(MemberDescriptor parameter)
=> base.Get(parameter.Metadata) ?? base.Get(parameter.MemberType);
public IAllowedValueSpecification Get(MemberDescriptor parameter)
=> _source.Get(parameter.Metadata) ?? _source.Get(parameter.MemberType);
}
}
}
72 changes: 72 additions & 0 deletions src/ExtendedXmlSerializer/Core/MetadataDictionary.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
using ExtendedXmlSerializer.ReflectionModel;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;

namespace ExtendedXmlSerializer.Core
{
class MetadataDictionary<T> : IDictionary<MemberInfo, T> where T : class
{
readonly IDictionary<MemberInfo, T> _primary, _secondary;

public MetadataDictionary(IDictionary<MemberInfo, T> primary)
: this(primary, primary.ToDictionary(x => x.Key, x => x.Value, InheritedMemberComparer.Default.Get())) {}

public MetadataDictionary(IDictionary<MemberInfo, T> primary, IDictionary<MemberInfo, T> secondary)
{
_primary = primary;
_secondary = secondary;
}

public IEnumerator<KeyValuePair<MemberInfo, T>> GetEnumerator() => _primary.GetEnumerator();

IEnumerator IEnumerable.GetEnumerator() => ((IEnumerable)_primary).GetEnumerator();

public void Add(KeyValuePair<MemberInfo, T> item)
{
throw new InvalidOperationException("Not supported.");
}

public void Clear()
{
throw new InvalidOperationException("Not supported.");
}

public bool Contains(KeyValuePair<MemberInfo, T> item) => _primary.Contains(item) || _secondary.Contains(item);

public void CopyTo(KeyValuePair<MemberInfo, T>[] array, int arrayIndex)
{
_primary.CopyTo(array, arrayIndex);
}

public bool Remove(KeyValuePair<MemberInfo, T> item) => throw new InvalidOperationException("Not supported.");

public int Count => _primary.Count;

public bool IsReadOnly => _primary.IsReadOnly;

public void Add(MemberInfo key, T value)
{
throw new InvalidOperationException("Not supported.");
}

public bool ContainsKey(MemberInfo key) => _primary.ContainsKey(key) || _secondary.ContainsKey(key);

public bool Remove(MemberInfo key) => throw new InvalidOperationException("Not supported.");

public bool TryGetValue(MemberInfo key, out T value)
=> _primary.TryGetValue(key, out value) || _secondary.TryGetValue(key, out value);

public T this[MemberInfo key]
{
get => _primary[key] ?? _secondary[key];
set => throw new InvalidOperationException("Not supported.");
}

public ICollection<MemberInfo> Keys => _primary.Keys;

public ICollection<T> Values => _primary.Values;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -63,11 +63,7 @@ public AllowedMemberValuesExtension(IAllowedValueSpecification allowed,
IAllowedMemberValues Register(IServiceProvider arg)
{
IParameterizedSource<MemberInfo, IAllowedValueSpecification>
seed = new MappedAllowedMemberValues(Specifications
.ToDictionary(x => x.Key, x => (ISpecification<object>)x.Value)
.Concat(Instances)
.GroupBy(x => x.Key)
.ToDictionary(x => x.Key, Create)),
seed = new Seeding(Specifications, Instances, _allowed).Get(),
fallback = _allowed == AllowAssignedValues
? Source.Default
: new FixedInstanceSource<MemberInfo, IAllowedValueSpecification>(_allowed);
Expand All @@ -77,6 +73,58 @@ IAllowedMemberValues Register(IServiceProvider arg)
return result;
}

sealed class Seeding : ISource<IAllowedMemberValues>
{
readonly IDictionary<MemberInfo, ISpecification<object>> _specifications;
readonly IDictionary<MemberInfo, ISpecification<object>> _instances;
readonly IAllowedValueSpecification _allowed;

public Seeding(IDictionary<MemberInfo, IAllowedValueSpecification> specifications,
IDictionary<MemberInfo, ISpecification<object>> instances,
IAllowedValueSpecification allowed)
: this(specifications.ToDictionary(x => x.Key, x => (ISpecification<object>)x.Value),
instances, allowed) {}

public Seeding(IDictionary<MemberInfo, ISpecification<object>> specifications,
IDictionary<MemberInfo, ISpecification<object>> instances,
IAllowedValueSpecification allowed)
{
_specifications = specifications;
_instances = instances;
_allowed = allowed;
}

public IAllowedMemberValues Get()
{
var primary = _specifications.Concat(_instances).GroupBy(x => x.Key).ToDictionary(x => x.Key, Create);
var result = new MappedAllowedMemberValues(new Dictionary(primary));
return result;
}

IAllowedValueSpecification Create(
IGrouping<MemberInfo, KeyValuePair<MemberInfo, ISpecification<object>>> parameter)
{
var item = parameter.Select(x => x.Value).ToArray();

var only = item.Only();
if (only != null)
{
return new
InstanceAwareValueSpecification(only is IAllowedValueSpecification allow ? allow : _allowed,
_instances.ContainsKey(parameter.Key)
? _instances[parameter.Key]
: AlwaysSpecification<object>.Default);
}

return new InstanceAwareValueSpecification(item.First(), item.Last());
}
}

sealed class Dictionary : MetadataDictionary<IAllowedValueSpecification>
{
public Dictionary(IDictionary<MemberInfo, IAllowedValueSpecification> primary) : base(primary) {}
}

sealed class Source : IParameterizedSource<MemberInfo, IAllowedValueSpecification>
{
public static IParameterizedSource<MemberInfo, IAllowedValueSpecification> Default { get; } = new Source();
Expand Down Expand Up @@ -125,24 +173,6 @@ public bool IsSatisfiedBy(object parameter)
: _previous.IsSatisfiedBy(parameter);
}

IAllowedValueSpecification Create(
IGrouping<MemberInfo, KeyValuePair<MemberInfo, ISpecification<object>>> parameter)
{
var item = parameter.Select(x => x.Value)
.ToArray();

var only = item.Only();
if (only != null)
{
return new InstanceAwareValueSpecification(only is IAllowedValueSpecification allow ? allow : _allowed,
Instances.ContainsKey(parameter.Key)
? Instances[parameter.Key]
: AlwaysSpecification<object>.Default);
}

return new InstanceAwareValueSpecification(item.First(), item.Last());
}

void ICommand<IServices>.Execute(IServices parameter) {}
}
}
6 changes: 6 additions & 0 deletions src/ExtendedXmlSerializer/ExtensionModel/Defaults.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,16 @@
using ExtendedXmlSerializer.ExtensionModel.References;
using ExtendedXmlSerializer.ReflectionModel;
using System.Reflection;

namespace ExtendedXmlSerializer.ExtensionModel
{
static class Defaults
{
public static TypeInfo Reference { get; } = typeof(ReferenceIdentity).GetTypeInfo();

public static ITypeComparer TypeComparer { get; }
= new CompositeTypeComparer(ImplementedTypeComparer.Default,
TypeIdentityComparer.Default,
InheritedTypeComparer.Default);
}
}
Original file line number Diff line number Diff line change
@@ -1,16 +1,11 @@
using ExtendedXmlSerializer.ReflectionModel;
using System.Collections.Generic;
using System.Collections.Generic;
using System.Reflection;

namespace ExtendedXmlSerializer.ExtensionModel.Xml
{
sealed class CustomSerializers : Metadata<TypeInfo, ContentModel.ISerializer>, ICustomSerializers
{
readonly static CompositeTypeComparer Comparer = new CompositeTypeComparer(ImplementedTypeComparer.Default,
TypeIdentityComparer.Default,
InheritedTypeComparer.Default);

public CustomSerializers() : this(Comparer) {}
public CustomSerializers() : this(ExtensionModel.Defaults.TypeComparer) {}

public CustomSerializers(IEqualityComparer<TypeInfo> comparer) : base(comparer) {}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
using ExtendedXmlSerializer.Core.Sources;
using System.Collections.Generic;
using System.Reflection;

namespace ExtendedXmlSerializer.ReflectionModel
{
sealed class InheritedMemberComparer : FixedInstanceSource<IEqualityComparer<MemberInfo>>
{
public static InheritedMemberComparer Default { get; } = new InheritedMemberComparer();

InheritedMemberComparer() : base(new MemberComparer(InheritedTypeComparer.Default)) {}
}
}
45 changes: 45 additions & 0 deletions test/ExtendedXmlSerializer.Tests.ReportedIssues/Issue411Tests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
using ExtendedXmlSerializer.Configuration;
using ExtendedXmlSerializer.Tests.ReportedIssues.Support;
using FluentAssertions;
using Xunit;

namespace ExtendedXmlSerializer.Tests.ReportedIssues
{
public sealed class Issue411Tests
{
[Fact]
public void Verify()
{
var serializer = new ConfigurationContainer().Type<SubjectBase>()
.Member(x => x.Message)
.EmitWhen(x => false)
.Create()
.ForTesting();

serializer.Cycle(new Subject {Message = "Hello World!"}).Message.Should().BeNull();
}


[Fact]
public void VerifyInstance()
{
var serializer = new ConfigurationContainer().Type<SubjectBase>()
.Member(x => x.Message)
.EmitWhenInstance(x => false)
.Create()
.ForTesting();

serializer.Cycle(new Subject {Message = "Hello World!"}).Message.Should().BeNull();
}

sealed class Subject : SubjectBase
{
public override string Message { get; set; }
}

public abstract class SubjectBase
{
public abstract string Message { get; set; }
}
}
}

0 comments on commit 0752564

Please sign in to comment.