Skip to content

Commit

Permalink
Added basic support for IEnumerable<T> for both instance and mem… (#343)
Browse files Browse the repository at this point in the history
* Added failing test.

* Added basic support for IEnumerable<T> for both instance and member property definitions.

* Adding documentation.
  • Loading branch information
Mike-EEE authored Dec 11, 2019
1 parent b5b6dee commit 697ab2e
Show file tree
Hide file tree
Showing 25 changed files with 399 additions and 64 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -31,5 +31,14 @@ public sealed class ElementDecorationContext<T> where T : IElement
/// <returns>The configured repository.</returns>
public IServiceRepository When(ISpecification<TypeInfo> specification)
=> new ConditionalElementDecoration<T>(specification).Get(_repository);

/// <summary>
/// Configures the container's <see cref="IElement"/> to use the decorated type when the provided specification is
/// satisfied.
/// </summary>
/// <typeparam name="TSpecification">The type of specification to activate via service location.</typeparam>
/// <returns>The configured repository</returns>
public IServiceRepository When<TSpecification>() where TSpecification : ISpecification<TypeInfo>
=> ConditionalElementDecoration<TSpecification, T>.Default.Get(_repository);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,4 @@ public ISerializer Get(CollectionContentInput parameter)
=> new Serializer(new ArrayReader(_contents, _classification, parameter.Classification, parameter.Item),
new EnumerableWriter(_enumerators, parameter.Item).Adapt());
}

// ATTRIBUTION: https://stackoverflow.com/a/1183019/3602057
}
4 changes: 2 additions & 2 deletions src/ExtendedXmlSerializer/ContentModel/Content/Container.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ namespace ExtendedXmlSerializer.ContentModel.Content
{
class Container<T> : SerializerAdapter<T>
{
public Container(IWriter<T> element, ISerializer<T> content) :
base(content, new Enclosure<T>(element, content)) {}
public Container(IWriter<T> element, ISerializer<T> content)
: base(content, new Enclosure<T>(element, content)) {}
}

sealed class Container : Container<object>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
using System.Reflection;
using ExtendedXmlSerializer.ContentModel.Collections;
using ExtendedXmlSerializer.Core.Sources;
using ExtendedXmlSerializer.ReflectionModel;
using System.Reflection;

namespace ExtendedXmlSerializer.ContentModel.Content
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ public Serializers(IElement element, IContents contents)
public ISerializer Get(TypeInfo parameter)
{
var element = _element.Get(parameter);
return new Container(element, _contents.Get(parameter));
var result = new Container(element, _contents.Get(parameter));
return result;
}
}
}

This file was deleted.

19 changes: 14 additions & 5 deletions src/ExtendedXmlSerializer/ContentModel/Members/MemberContents.cs
Original file line number Diff line number Diff line change
@@ -1,15 +1,24 @@
using ExtendedXmlSerializer.Core.Sources;
using ExtendedXmlSerializer.Core.Specifications;
using JetBrains.Annotations;

namespace ExtendedXmlSerializer.ContentModel.Members
{
sealed class MemberContents : DecoratedSource<IMember, ISerializer>, IMemberContents
interface IMemberContentsCore : IMemberContents {}

[UsedImplicitly]
sealed class MemberContentsCore : DecoratedSource<IMember, ISerializer>, IMemberContentsCore
{
readonly static ISpecification<IMember> Specification = VariableTypeMemberSpecifications.Default.IfAssigned();

public MemberContents(DefaultMemberContents @default, VariableTypeMemberContents variable,
RegisteredMemberContents registered)
: base(@default.Let(Specification, variable)
.Let(registered, registered)) {}
public MemberContentsCore(DefaultMemberContents @default, VariableTypeMemberContents variable)
: base(@default.Let(Specification, variable)) {}
}

[UsedImplicitly]
sealed class MemberContents : DecoratedSource<IMember, ISerializer>, IMemberContents
{
public MemberContents(IMemberContentsCore core, RegisteredMemberContents registered)
: base(core.Let(registered, registered)) {}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,7 @@ public void Write(IFormatWriter writer, object instance)
var length = members.Length;
for (var i = 0; i < length; i++)
{
members[i]
.Write(writer, instance);
members[i].Write(writer, instance);
}
}
else
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,8 @@

namespace ExtendedXmlSerializer.ContentModel.Members
{
sealed class VariableTypeMemberSpecifications
: ReferenceCacheBase<IMember, IVariableTypeSpecification>,
IVariableTypeMemberSpecifications
sealed class VariableTypeMemberSpecifications : ReferenceCacheBase<IMember, IVariableTypeSpecification>,
IVariableTypeMemberSpecifications
{
public static VariableTypeMemberSpecifications Default { get; } = new VariableTypeMemberSpecifications();

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
using ExtendedXmlSerializer.ContentModel.Content;
using System;
using System.Reflection;
using ExtendedXmlSerializer.ContentModel.Content;

namespace ExtendedXmlSerializer.ContentModel
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
using System.Reflection;
using ExtendedXmlSerializer.ContentModel.Content;
using ExtendedXmlSerializer.ContentModel.Format;
using ExtendedXmlSerializer.ContentModel.Reflection;
using JetBrains.Annotations;
using System.Reflection;

namespace ExtendedXmlSerializer.ContentModel
{
Expand Down
12 changes: 12 additions & 0 deletions src/ExtendedXmlSerializer/ExtensionMethodsForContent.cs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,18 @@ public static ElementDecorationContext<T> DecorateElementWith<T>(this IServiceRe

/* Extension Model: */

/// <summary>
/// Adds support for instances and property types that are explicitly specified as `IEnumerable{T}`. If an object is
/// of a type of `IEnumerable` (essentially, a deferred query), it will be evaluated as a <see cref="List{T}"/> and
/// saved as such as required by either the instance or property in the object graph.
/// </summary>
/// <param name="this">The configuration container to configure.</param>
/// <returns>The configured configuration container.</returns>
/// <seealso href="https://github.com/ExtendedXmlSerializer/home/issues/340" />
/// <seealso href="https://twitter.com/vcsjones/status/1204432274000879619" />
public static IConfigurationContainer WithEnumerableSupport(this IConfigurationContainer @this)
=> @this.Extend(EnumerableSupportExtension.Default);

/// <summary>
/// Assigns a default serialization monitor for a configuration container. A serialization monitor is a component
/// that gets notified whenever there is a serialization such as OnSerializing, OnSerialized, as well as
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
using System.Reflection;
using ExtendedXmlSerializer.ContentModel;
using ExtendedXmlSerializer.ContentModel.Content;
using ExtendedXmlSerializer.Core;
using ExtendedXmlSerializer.Core.Sources;
using ExtendedXmlSerializer.Core.Specifications;
using ExtendedXmlSerializer.ReflectionModel;
using System.Linq;
using System.Reflection;

namespace ExtendedXmlSerializer.ExtensionModel.Content
{
Expand All @@ -19,4 +23,27 @@ sealed class Factory
public IElement Create(IElement element, T arg2) => new ConditionalElement(_specification, arg2, element);
}
}

sealed class ConditionalElementDecoration<TSpecification, T> : IAlteration<IServiceRepository>
where T : IElement where TSpecification : ISpecification<TypeInfo>
{
public static ConditionalElementDecoration<TSpecification, T> Default { get; } =
new ConditionalElementDecoration<TSpecification, T>();

ConditionalElementDecoration() {}

public IServiceRepository Get(IServiceRepository parameter)
{
var key = Support<TSpecification>.Metadata;
var repository = key.IsClass &&
!parameter.AvailableServices.Contains(key)
? parameter.RegisterWithDependencies<TSpecification>()
: parameter;
return repository.RegisterWithDependencies<T>()
.Decorate<IElement>(Create);
}

static IElement Create(IServiceProvider arg1, IElement arg2)
=> new ConditionalElement(arg1.Get<TSpecification>(), arg1.Get<T>(), arg2);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
using ExtendedXmlSerializer.Core;
using ExtendedXmlSerializer.Core.Sources;
using ExtendedXmlSerializer.ReflectionModel;
using VariableTypeSpecification = ExtendedXmlSerializer.ReflectionModel.VariableTypeSpecification;

namespace ExtendedXmlSerializer.ExtensionModel.Content
{
Expand Down Expand Up @@ -42,8 +41,6 @@ public IServiceRepository Get(IServiceRepository parameter)
=> parameter.Register<RuntimeElement>()
.Register<Element>()
.Register<IElement, Element>()
.DecorateElementWith<VariableTypeElement>()
.When(VariableTypeSpecification.Default)
.DecorateElementWith<GenericElement>()
.When(IsGenericTypeSpecification.Default)
.DecorateElementWith<ArrayElement>()
Expand Down
9 changes: 9 additions & 0 deletions src/ExtendedXmlSerializer/ExtensionModel/Content/Contents.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,22 +24,31 @@ public sealed class Contents : ISerializerExtension
public IServiceRepository Get(IServiceRepository parameter)
=> parameter.RegisterConstructorDependency<IContents>((provider, info) => provider.Get<DeferredContents>())
.Register<IContents, RuntimeContents>()

.DecorateContentsWith<MemberedContents>()
.When<IActivatingTypeSpecification>()

.DecorateContentsWith<DefaultCollections>()
.When<DefaultCollectionSpecification>()

.Register<IDictionaryEntries, DictionaryEntries>()
.DecorateContentsWith<DictionaryContents>()
.When<DictionaryContentSpecification>()

.DecorateContentsWith<Arrays>()
.When(ArraySpecification.Default)

.DecorateContentsWith<MappedArrayContents>()
.Then()

.RegisterInstance(ReflectionSerializer.Default)

.DecorateContentsWith<ReflectionContents>()
.When(ReflectionContentSpecification.Default)

.DecorateContentsWith<NullableContents>()
.When(IsNullableTypeSpecification.Default)

.DecorateContentsWith<ConverterContents>()
.When<ConverterSpecification>()
.DecorateContentsWith<RegisteredContents>()
Expand Down
Loading

0 comments on commit 697ab2e

Please sign in to comment.