Skip to content

Commit

Permalink
Improved member resolution for parameterized content (#428)
Browse files Browse the repository at this point in the history
  • Loading branch information
Mike-E-angelo authored Aug 16, 2020
1 parent 02adccc commit 9d372a3
Show file tree
Hide file tree
Showing 12 changed files with 171 additions and 28 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System.Reflection;
using ExtendedXmlSerializer.ContentModel.Reflection;
using ExtendedXmlSerializer.Core.Specifications;
using ExtendedXmlSerializer.ExtensionModel.Types;
using System.Reflection;

namespace ExtendedXmlSerializer.ContentModel.Members
{
Expand All @@ -23,8 +24,7 @@ public InstanceMemberSerialization(ISpecification<TypeInfo> specification, IMemb

public IMemberSerialization Get(object parameter)
{
var type = parameter.GetType()
.GetTypeInfo();
var type = parameter is ITypeAware aware ? aware.Get() : parameter.GetType().GetTypeInfo();
var result = _specification.IsSatisfiedBy(type) ? _serializations.Get(type) : _serialization;
return result;
}
Expand Down
18 changes: 18 additions & 0 deletions src/ExtendedXmlSerializer/ContentModel/Members/MemberContext.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
using System.Collections.Immutable;
using System.Reflection;

namespace ExtendedXmlSerializer.ContentModel.Members
{
readonly struct MemberContext
{
public MemberContext(TypeInfo reflectedType, ImmutableArray<IMember> members)
{
ReflectedType = reflectedType;
Members = members;
}

public TypeInfo ReflectedType { get; }

public ImmutableArray<IMember> Members { get; }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,11 @@ public MemberInnerContentHandler(IInstanceMemberSerialization serialization, IMe

public bool IsSatisfiedBy(IInnerContent parameter)
{
var content = parameter.Get();
var key = _formatter.Get(content);
var member = _serialization.Get(parameter.Current)
.Get(key);
var result = member != null;
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)
{
_handler.Handle(parameter, member);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,8 @@ public IActivator Get(Type parameter)
ActivationContextActivator Activator(ConstructorInfo constructor, ImmutableArray<IMember> members)
{
var activator = new Source(constructor).ToSelectionDelegate();
var contexts = new ActivationContexts(_accessors, members, activator);
var context = new MemberContext(constructor.ReflectedType.GetTypeInfo(), members);
var contexts = new ActivationContexts(_accessors, context, activator);
var defaults = constructor.GetParameters()
.Where(x => x.IsOptional)
.Select(x => Pairs.Create(x.Name, x.DefaultValue))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,8 @@ public IActivator Get(Type parameter)
ActivationContextActivator Activator(ConstructorInfo constructor, ImmutableArray<IMember> members)
{
var activator = new Source(constructor).ToSelectionDelegate();
var contexts = new ActivationContexts(_accessors, members, activator);
var context = new MemberContext(constructor.ReflectedType.GetTypeInfo(), members);
var contexts = new ActivationContexts(_accessors, context, activator);
var defaults = constructor.GetParameters()
.Where(x => x.IsOptional)
.Select(x => Pairs.Create(x.Name, x.DefaultValue))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,16 @@
using ExtendedXmlSerializer.Core;
using ExtendedXmlSerializer.Core.Parsing;
using ExtendedXmlSerializer.Core.Sources;
using Sprache;
using ExtendedXmlSerializer.ExtensionModel.Expressions;
using ExtendedXmlSerializer.ExtensionModel.Types;
using ExtendedXmlSerializer.ReflectionModel;
using Sprache;
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using System.Reflection;

// ReSharper disable TooManyDependencies

namespace ExtendedXmlSerializer.ExtensionModel.Markup
Expand Down Expand Up @@ -79,7 +80,8 @@ protected override object Create(MarkupExtensionParts parameter)
.Zip(candidates, (info, evaluation) => evaluation.Get(info))
.ToArray();
var activator = new ConstructedActivator(constructor, arguments);
var extension = new ActivationContexts(_accessors, members, activator).Get(dictionary)
var context = new MemberContext(constructor.ReflectedType.GetTypeInfo(), members);
var extension = new ActivationContexts(_accessors, context, activator).Get(dictionary)
.Get()
.AsValid<IMarkupExtension>();
var result = extension.ProvideValue(new Provider(_provider, _services.Appending(parameter)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,22 @@
using ExtendedXmlSerializer.Core.Sources;
using System;
using System.Collections;
using ExtendedXmlSerializer.Core.Sources;
using System.Reflection;

namespace ExtendedXmlSerializer.ExtensionModel.Types
{
sealed class ActivationContext : IActivationContext
sealed class ActivationContext : IActivationContext, ITypeAware
{
readonly TypeInfo _subject;
readonly ITableSource<string, object> _source;
readonly Func<object> _activator;
readonly IList _list;

public ActivationContext(ITableSource<string, object> source, Func<object> activator, IList list)
// ReSharper disable once TooManyDependencies
public ActivationContext(TypeInfo subject, ITableSource<string, object> source, Func<object> activator,
IList list)
{
_subject = subject;
_source = source;
_activator = activator;
_list = list;
Expand Down Expand Up @@ -60,5 +65,7 @@ public object this[int index]
get => _list[index];
set => _list[index] = value;
}

TypeInfo ISource<TypeInfo>.Get() => _subject;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,30 +5,30 @@
using ExtendedXmlSerializer.ReflectionModel;
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;

namespace ExtendedXmlSerializer.ExtensionModel.Types
{
sealed class ActivationContexts : IActivationContexts
{
readonly IMemberAccessors _accessors;
readonly ImmutableArray<IMember> _members;
readonly MemberContext _members;
readonly ITableSource<string, IMember> _table;
readonly Func<Func<string, object>, IActivator> _activator;

public ActivationContexts(IMemberAccessors accessors, ImmutableArray<IMember> members, IActivator activator)
public ActivationContexts(IMemberAccessors accessors, MemberContext members, IActivator activator)
: this(accessors, members, activator.Accept) {}

public ActivationContexts(IMemberAccessors accessors, ImmutableArray<IMember> members,
public ActivationContexts(IMemberAccessors accessors, MemberContext members,
Func<Func<string, object>, IActivator> activator)
: this(accessors, members,
new TableSource<string, IMember>(members.ToDictionary(x => x.Name,
new TableSource<string, IMember>(members.Members
.ToDictionary(x => x.Name,
StringComparer.InvariantCultureIgnoreCase)),
activator) {}

// ReSharper disable once TooManyDependencies
public ActivationContexts(IMemberAccessors accessors, ImmutableArray<IMember> members,
public ActivationContexts(IMemberAccessors accessors, MemberContext members,
ITableSource<string, IMember> table,
Func<Func<string, object>, IActivator> activator)
{
Expand All @@ -42,12 +42,12 @@ public IActivationContext Get(IDictionary<string, object> parameter)
{
var source = new TableSource<string, object>(parameter);
var list = new List<object>();
var command = new CompositeCommand<object>(new ApplyMemberValuesCommand(_accessors, _members, source),
var command = new CompositeCommand<object>(new ApplyMemberValuesCommand(_accessors, _members.Members,
source),
new AddItemsCommand(list));
var alteration = new ConfiguringAlteration<object>(command);
var activator = new AlteringActivator(alteration, _activator(new Store(source, _table).Get));
var result = new ActivationContext(source, activator.Singleton()
.Get, list);
var result = new ActivationContext(_members.ReflectedType, source, activator.Singleton().Get, list);
return result;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
using System.Collections;
using ExtendedXmlSerializer.Core.Sources;
using ExtendedXmlSerializer.ReflectionModel;
using System.Collections;

namespace ExtendedXmlSerializer.ExtensionModel.Types
{
Expand Down
7 changes: 7 additions & 0 deletions src/ExtendedXmlSerializer/ExtensionModel/Types/ITypeAware.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
using ExtendedXmlSerializer.Core.Sources;
using System.Reflection;

namespace ExtendedXmlSerializer.ExtensionModel.Types
{
interface ITypeAware : ISource<TypeInfo> {}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
using System.Collections.Immutable;
using ExtendedXmlSerializer.ContentModel.Members;
using ExtendedXmlSerializer.Core;
using ExtendedXmlSerializer.Core.Sources;
using System.Collections.Immutable;

namespace ExtendedXmlSerializer.ReflectionModel
{
Expand All @@ -23,8 +23,7 @@ public void Execute(object parameter)
{
foreach (var member in _members)
{
var isSatisfiedBy = _values.IsSatisfiedBy(member.Name);
if (isSatisfiedBy)
if (_values.IsSatisfiedBy(member.Name))
{
var access = _accessors.Get(member);
var value = _values.Get(member.Name);
Expand Down
108 changes: 108 additions & 0 deletions test/ExtendedXmlSerializer.Tests.ReportedIssues/Issue427Tests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
using ExtendedXmlSerializer.Configuration;
using ExtendedXmlSerializer.Tests.ReportedIssues.Support;
using FluentAssertions;
using System.Linq;
using Xunit;
// ReSharper disable UnusedAutoPropertyAccessor.Local

namespace ExtendedXmlSerializer.Tests.ReportedIssues
{
public sealed class Issue427Tests
{
[Fact]
public void Verify()
{
var instance = new Subject("Hello World", 123);
var serializer = new ConfigurationContainer().EnableParameterizedContent().Create().ForTesting();

serializer.Cycle(instance).Should().BeEquivalentTo(instance);

var element = new Base[] {instance};
serializer.Cycle(element).Should().BeEquivalentTo(element.Cast<Subject>());

}

[Fact]
public void VerifyBasic()
{
var instance = new BasicSubject{Name = "Hello World", Number = 123};
var serializer = new ConfigurationContainer().Create().ForTesting();

serializer.Cycle(instance).Should().BeEquivalentTo(instance);

var element = new Basic[] {instance};
serializer.Cycle(element).Should().BeEquivalentTo(element.Cast<Basic>());

}

[Fact]
public void VerifyReported()
{
var config = new NewFieldInfo(FieldType.Int)
{
Name = "abc",
TargetName = "edf"
};

var serializer = new ConfigurationContainer().EnableParameterizedContentWithPropertyAssignments()
.Create()
.ForTesting();

var instance = new NewTypeInfo[] {config};
serializer.Cycle(instance).Should().BeEquivalentTo(instance.Cast<NewFieldInfo>());
}

class BasicSubject : Basic
{
public string Name { get; set; }
}

class Basic
{
public int Number { get; set; }
}

class Subject : Base
{
public Subject(string name, int number) : base(number) => Name = name;

public string Name { get; }
}

class Base
{
public Base(int number) => Number = number;

public int Number { get; }
}

public enum FieldType
{
Int,
Bool
}

public class NewFieldInfo : NewTypeInfo
{
public NewFieldInfo(FieldType type) : base(type) {}

public string Description { get; set; } = null;

public bool IsRequired { get; set; }

public string TargetName { get; set; }
}

public class NewTypeInfo
{
public NewTypeInfo(FieldType type)
{
Type = type;
}

public FieldType Type { get; }

public string Name { get; set; }
}
}
}

0 comments on commit 9d372a3

Please sign in to comment.