Skip to content

Commit

Permalink
Added support for System.Collections.Immutable Types (#486)
Browse files Browse the repository at this point in the history
  • Loading branch information
Mike-E-angelo authored Dec 7, 2020
1 parent 90345c7 commit f74f8c3
Show file tree
Hide file tree
Showing 33 changed files with 1,416 additions and 137 deletions.
6 changes: 3 additions & 3 deletions src/ExtendedXmlSerializer/Configuration/EmitBehaviors.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using ExtendedXmlSerializer.ContentModel.Members;
using ExtendedXmlSerializer.ContentModel.Reflection;
using ExtendedXmlSerializer.ExtensionModel.Content.Members;
using ExtendedXmlSerializer.ExtensionModel.Xml.Classic;
using System;
Expand Down Expand Up @@ -35,14 +36,13 @@ public static class EmitBehaviors
/// MyProperty {get; set} = true` and `MyProperty` is `false` upon serialization, then the content is emitted.
/// </summary>
public static IEmitBehavior WhenModified { get; } =
new EmitBehavior(new AddAlteration(AllowedAssignedInstanceValues.Default));
new EmitBehavior(new AddAlteration(new AllowedAssignedInstanceValues(new TypeMemberDefaults(DefaultTypeDefaults.Default))));

#region Obsolete

/// <exclude />
[Obsolete("This is considered deprecated and will be removed in a future release. Use EmitBehaviors.WhenModified instead.")]
public static IEmitBehavior Assigned { get; } =
new EmitBehavior(new AddAlteration(AllowedAssignedInstanceValues.Default));
public static IEmitBehavior Assigned { get; } = WhenModified;

/// <exclude />
[Obsolete("This is considered deprecated and will be removed in a future release. Use EmitBehaviors.WhenAssigned instead.")]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,14 @@

namespace ExtendedXmlSerializer.ContentModel.Members
{
class AllowedAssignedInstanceValues : IAllowedMemberValues
sealed class AllowedAssignedInstanceValues : IAllowedMemberValues
{
readonly ISpecification<TypeInfo> _specification;
readonly ITypeMemberDefaults _defaults;
readonly IGeneric<object, ISpecification<object>> _generic;

public static AllowedAssignedInstanceValues Default { get; } = new AllowedAssignedInstanceValues();

AllowedAssignedInstanceValues()
: this(ActivatingTypeSpecification.Default, TypeMemberDefaults.Default,
public AllowedAssignedInstanceValues(ITypeMemberDefaults defaults)
: this(ActivatingTypeSpecification.Default, defaults,
new Generic<object, ISpecification<object>>(typeof(Specification<>))) {}

public AllowedAssignedInstanceValues(ISpecification<TypeInfo> specification, ITypeMemberDefaults defaults,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
using ExtendedXmlSerializer.Core.Sources;
using ExtendedXmlSerializer.ReflectionModel;
using System.Reflection;

namespace ExtendedXmlSerializer.ContentModel.Reflection
{
sealed class DefaultTypeDefaults : DecoratedSource<TypeInfo, object>, ITypeDefaults
{
public static DefaultTypeDefaults Default { get; } = new DefaultTypeDefaults();

DefaultTypeDefaults() : base(new TypeDefaults(DefaultConstructedActivators.Default)) {}
}
}
Original file line number Diff line number Diff line change
@@ -1,23 +1,22 @@
using System.Reflection;
using ExtendedXmlSerializer.Core.Sources;
using ExtendedXmlSerializer.ReflectionModel;
using System.Reflection;

namespace ExtendedXmlSerializer.ContentModel.Reflection
{
sealed class TypeDefaults : ReferenceCacheBase<TypeInfo, object>, ITypeDefaults
{
public static TypeDefaults Default { get; } = new TypeDefaults();
public static IParameterizedSource<IActivators, ITypeDefaults> Defaults { get; }
= new ReferenceCache<IActivators, ITypeDefaults>(key => new TypeDefaults(key));

/*public static TypeDefaults Default { get; } = new TypeDefaults();
TypeDefaults() : this(DefaultActivators.Default) {}
TypeDefaults() : this(DefaultActivators.Default) {}*/

readonly IActivators _activators;

public TypeDefaults(IActivators activators)
{
_activators = activators;
}
public TypeDefaults(IActivators activators) => _activators = activators;

protected override object Create(TypeInfo parameter) => _activators.Get(parameter.AsType())
.Get();
protected override object Create(TypeInfo parameter) => _activators.Get(parameter.AsType()).Get();
}
}
Original file line number Diff line number Diff line change
@@ -1,22 +1,19 @@
using System;
using System.Reflection;
using ExtendedXmlSerializer.ContentModel.Members;
using ExtendedXmlSerializer.Core.Sources;
using System;
using System.Reflection;

namespace ExtendedXmlSerializer.ContentModel.Reflection
{
sealed class TypeMemberDefaults : ReferenceCacheBase<TypeInfo, Func<MemberInfo, object>>, ITypeMemberDefaults
{
public static TypeMemberDefaults Default { get; } = new TypeMemberDefaults();
/*public static TypeMemberDefaults Default { get; } = new TypeMemberDefaults();
TypeMemberDefaults() : this(TypeDefaults.Default) {}
TypeMemberDefaults() : this(TypeDefaults.Default) {}*/

readonly ITypeDefaults _defaults;

public TypeMemberDefaults(ITypeDefaults defaults)
{
_defaults = defaults;
}
public TypeMemberDefaults(ITypeDefaults defaults) => _defaults = defaults;

protected override Func<MemberInfo, object> Create(TypeInfo parameter)
=> new MemberDefaults(_defaults.Get(parameter)).Get;
Expand Down
15 changes: 14 additions & 1 deletion src/ExtendedXmlSerializer/ExtensionMethodsForExtensionModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,19 @@ public static IConfigurationContainer EnableMarkupExtensions(this IConfiguration
public static IConfigurationContainer EnableAllConstructors(this IConfigurationContainer @this)
=> @this.Extend(AllConstructorsExtension.Default);

/// <summary>
/// Enables the use of types found in the `System.Collections.Immutable` namespace.
/// </summary>
/// <param name="this">The configuration container to configure.</param>
/// <returns>The configured configuration container.</returns>
/// <seealso href="https://github.com/ExtendedXmlSerializer/home/issues/485" />
public static IConfigurationContainer EnableImmutableTypes(this IConfigurationContainer @this)
=> @this.Extend(ImmutableListExtension.Default)
.Extend(ImmutableHashSetExtension.Default)
.Extend(ImmutableSortedSetExtension.Default)
.Extend(ImmutableDictionariesExtension.Default)
.Extend(ImmutableSortedDictionariesExtension.Default);

#region Obsolete

/// <summary>
Expand Down Expand Up @@ -217,7 +230,7 @@ public static IConfigurationContainer AllowExistingInstances(this IConfiguration
/// <returns></returns>
/// <seealso cref="UnknownContentContext.Call"/>
[Obsolete(
"This method is being deprecated. Please use ConfigurationContainer.WithUnknownContent.Call instead.")]
"This method is being deprecated. Please use ConfigurationContainer.WithUnknownContent.Call instead.")]
public static IConfigurationContainer EnableUnknownContentHandling(this IConfigurationContainer @this,
Action<IFormatReader> onMissing)
=> @this.WithUnknownContent().Call(onMissing);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ namespace ExtendedXmlSerializer
/// </summary>
public static class ExtensionMethodsForSerialization
{
readonly static Func<Stream> New = DefaultActivators.Default.New<MemoryStream>;
readonly static Func<Stream> New = DefaultConstructedActivators.Default.New<MemoryStream>;

readonly static IXmlWriterFactory WriterFactory
= new XmlWriterFactory(CloseSettings.Default.Get(ExtensionModel.Xml.Defaults.WriterSettings));
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
using System;
using ExtendedXmlSerializer.ContentModel.Conversion;
using ExtendedXmlSerializer.ContentModel.Conversion;
using ExtendedXmlSerializer.ContentModel.Reflection;
using ExtendedXmlSerializer.Core.Parsing;
using ExtendedXmlSerializer.Core.Sources;
using System;

namespace ExtendedXmlSerializer.ExtensionModel.Content
{
Expand All @@ -15,7 +15,7 @@ sealed class ImplicitlyDefinedDefaultValueAlteration : IAlteration<IConverter>

public IConverter Get(IConverter parameter)
{
var @default = TypeDefaults.Default.Get(parameter.Get());
var @default = DefaultTypeDefaults.Default.Get(parameter.Get());
var parser = new Parser(parameter.Parse, @default);
var result = new Converter<object>(parameter, parser.Get, parameter.Format);
return result;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using ExtendedXmlSerializer.ContentModel.Members;
using ExtendedXmlSerializer.ContentModel.Reflection;
using ExtendedXmlSerializer.Core;
using ExtendedXmlSerializer.Core.Sources;
using ExtendedXmlSerializer.ExtensionModel.Types;
Expand All @@ -16,18 +17,27 @@ sealed class AllMembersParameterizedActivators : IActivators
readonly IQueriedConstructors _constructors;
readonly IMemberAccessors _accessors;
readonly ITypeMembers _typeMembers;
readonly ITypeDefaults _defaults;
readonly IConstructorMembers _members;

// ReSharper disable once TooManyDependencies
public AllMembersParameterizedActivators(IActivators activators, IQueriedConstructors constructors,
IConstructorMembers members, IMemberAccessors accessors,
ITypeMembers typeMembers)
: this(activators, constructors, members, accessors, typeMembers,
new ParameterizedAwareTypeDefaults(TypeDefaults.Defaults.Get(activators), constructors)) {}

// ReSharper disable once TooManyDependencies
public AllMembersParameterizedActivators(IActivators activators, IQueriedConstructors constructors,
IConstructorMembers members, IMemberAccessors accessors,
ITypeMembers typeMembers, ITypeDefaults defaults)
{
_activators = activators;
_constructors = constructors;
_members = members;
_accessors = accessors;
_typeMembers = typeMembers;
_defaults = defaults;
}

public IActivator Get(Type parameter)
Expand All @@ -46,7 +56,7 @@ ActivationContextActivator Activator(ConstructorInfo constructor, ImmutableArray
{
var activator = new Source(constructor).ToSelectionDelegate();
var context = new MemberContext(constructor.ReflectedType.GetTypeInfo(), members);
var contexts = new ActivationContexts(_accessors, context, activator);
var contexts = new ActivationContexts(_accessors, context, activator, _defaults);
var defaults = constructor.GetParameters()
.Where(x => x.IsOptional)
.Select(x => Pairs.Create(x.Name, x.DefaultValue))
Expand All @@ -65,7 +75,10 @@ public IActivator Get(Func<string, object> parameter)
{
var arguments = new Enumerable<object>(_constructor.GetParameters()
.Select(x => x.Name)
.Select(parameter));
.Select(parameter)
.Select(x => x is IActivationAware aware
? aware.Get()
: x));
var result = new ConstructedActivator(_constructor, arguments);
return result;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
using ExtendedXmlSerializer.ContentModel.Reflection;
using ExtendedXmlSerializer.Core.Sources;
using ExtendedXmlSerializer.ReflectionModel;
using System.Reflection;

namespace ExtendedXmlSerializer.ExtensionModel.Content.Members
{
sealed class DefaultValueTypeDefaults : ITypeDefaults
{
public static DefaultValueTypeDefaults Default { get; } = new DefaultValueTypeDefaults();

DefaultValueTypeDefaults() : this(new Generic<ISource<object>>(typeof(DefaultValues<>))) {}

readonly IGeneric<ISource<object>> _generic;

public DefaultValueTypeDefaults(IGeneric<ISource<object>> generic) => _generic = generic;

public object Get(TypeInfo parameter) => _generic.Get(parameter)().Get();
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using ExtendedXmlSerializer.ContentModel.Members;
using ExtendedXmlSerializer.ContentModel.Reflection;
using ExtendedXmlSerializer.Core;
using ExtendedXmlSerializer.Core.Sources;
using ExtendedXmlSerializer.ExtensionModel.Types;
Expand All @@ -15,16 +16,24 @@ sealed class ParameterizedActivators : IActivators
readonly IActivators _activators;
readonly IQueriedConstructors _constructors;
readonly IMemberAccessors _accessors;
readonly ITypeDefaults _defaults;
readonly IConstructorMembers _members;

// ReSharper disable once TooManyDependencies
public ParameterizedActivators(IActivators activators, IQueriedConstructors constructors,
IConstructorMembers members, IMemberAccessors accessors)
: this(activators, constructors, members, accessors,
new ParameterizedAwareTypeDefaults(TypeDefaults.Defaults.Get(activators), constructors)) {}

// ReSharper disable once TooManyDependencies
public ParameterizedActivators(IActivators activators, IQueriedConstructors constructors,
IConstructorMembers members, IMemberAccessors accessors, ITypeDefaults defaults)
{
_activators = activators;
_constructors = constructors;
_members = members;
_accessors = accessors;
_defaults = defaults;
}

public IActivator Get(Type parameter)
Expand All @@ -42,7 +51,7 @@ ActivationContextActivator Activator(ConstructorInfo constructor, ImmutableArray
{
var activator = new Source(constructor).ToSelectionDelegate();
var context = new MemberContext(constructor.ReflectedType.GetTypeInfo(), members);
var contexts = new ActivationContexts(_accessors, context, activator);
var contexts = new ActivationContexts(_accessors, context, activator, _defaults);
var defaults = constructor.GetParameters()
.Where(x => x.IsOptional)
.Select(x => Pairs.Create(x.Name, x.DefaultValue))
Expand All @@ -61,7 +70,10 @@ public IActivator Get(Func<string, object> parameter)
{
var arguments = new Enumerable<object>(_constructor.GetParameters()
.Select(x => x.Name)
.Select(parameter));
.Select(parameter)
.Select(x => x is IActivationAware aware
? aware.Get()
: x));
var result = new ConstructedActivator(_constructor, arguments);
return result;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
using ExtendedXmlSerializer.ContentModel.Reflection;
using ExtendedXmlSerializer.ExtensionModel.Types;
using System.Reflection;

namespace ExtendedXmlSerializer.ExtensionModel.Content.Members
{
sealed class ParameterizedAwareTypeDefaults : ITypeDefaults
{
readonly ITypeDefaults _previous;
readonly IQueriedConstructors _constructors;
readonly ITypeDefaults _defaults;

public ParameterizedAwareTypeDefaults(ITypeDefaults previous, IQueriedConstructors constructors)
: this(previous, constructors, DefaultValueTypeDefaults.Default) {}

public ParameterizedAwareTypeDefaults(ITypeDefaults previous, IQueriedConstructors constructors,
ITypeDefaults defaults)
{
_previous = previous;
_constructors = constructors;
_defaults = defaults;
}

public object Get(TypeInfo parameter)
{
var defaults = _constructors.Get(parameter) != null ? _defaults : _previous;
var result = defaults.Get(parameter);
return result;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using ExtendedXmlSerializer.ContentModel.Identification;
using ExtendedXmlSerializer.ContentModel.Members;
using ExtendedXmlSerializer.ContentModel.Properties;
using ExtendedXmlSerializer.ContentModel.Reflection;
using ExtendedXmlSerializer.Core;
using ExtendedXmlSerializer.Core.Parsing;
using ExtendedXmlSerializer.Core.Sources;
Expand Down Expand Up @@ -33,17 +34,21 @@ sealed class MarkupExtensionPartsEvaluator
readonly IConstructors _constructors;
readonly System.IServiceProvider _provider;
readonly IFormatter<TypeParts> _formatter;
readonly ITypeDefaults _defaults;
readonly object[] _services;

public MarkupExtensionPartsEvaluator(IParser<MemberInfo> parser, IEvaluator evaluator, ITypeMembers members,
public MarkupExtensionPartsEvaluator(IActivators activators,
IParser<MemberInfo> parser, IEvaluator evaluator, ITypeMembers members,
IMemberAccessors accessors, IConstructors constructors,
System.IServiceProvider provider, params object[] services)
System.IServiceProvider provider,
params object[] services)
: this(parser, evaluator, members, accessors, constructors, provider, TypePartsFormatter.Default,
services) {}
TypeDefaults.Defaults.Get(activators), services) {}

public MarkupExtensionPartsEvaluator(IParser<MemberInfo> parser, IEvaluator evaluator, ITypeMembers members,
IMemberAccessors accessors, IConstructors constructors,
System.IServiceProvider provider, IFormatter<TypeParts> formatter,
ITypeDefaults defaults,
params object[] services)
{
_parser = parser;
Expand All @@ -53,6 +58,7 @@ public MarkupExtensionPartsEvaluator(IParser<MemberInfo> parser, IEvaluator eval
_constructors = constructors;
_provider = provider;
_formatter = formatter;
_defaults = defaults;
_services = services;
}

Expand Down Expand Up @@ -81,9 +87,10 @@ protected override object Create(MarkupExtensionParts parameter)
.ToArray();
var activator = new ConstructedActivator(constructor, arguments);
var context = new MemberContext(constructor.ReflectedType.GetTypeInfo(), members);
var extension = new ActivationContexts(_accessors, context, activator).Get(dictionary)
.Get()
.AsValid<IMarkupExtension>();
var extension = new ActivationContexts(_accessors, context, activator, _defaults)
.Get(dictionary)
.Get()
.AsValid<IMarkupExtension>();
var result = extension.ProvideValue(new Provider(_provider, _services.Appending(parameter)
.ToArray()));
return result;
Expand Down
Loading

0 comments on commit f74f8c3

Please sign in to comment.