예제 #1
0
        public ITypeSerializerStrategy <TType> Create <TType>([NotNull] ISerializableTypeContext context)
        {
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            if (!CanHandle(context))
            {
                throw new InvalidOperationException($"Cannot handle Type: {context.TargetType.Name} with a {this.GetType().FullName}.");
            }

            if (!context.BuiltContextKey.HasValue)
            {
                throw new InvalidOperationException($"Failed to build a {nameof(ContextualSerializerLookupKey)} for the Type: {context.TargetType} with Context: {context.ToString()}.");
            }

            ITypeSerializerStrategy <TType> serializer = TryCreateSerializer <TType>(context);

            if (serializer == null)
            {
                throw new InvalidOperationException($"Failed to generate a serializer for Type: {context.TargetType.Name} with decorator factory {this.GetType().FullName}.");
            }

            return(serializer);
        }
예제 #2
0
        /// <inheritdoc />
        public override bool CanHandle(ISerializableTypeContext context)
        {
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context), $"Provided argument {nameof(context)} was null.");
            }

            return(context.TargetType.IsArray);
        }
        public static bool HasContextualKey([NotNull] this ISerializableTypeContext context)
        {
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            return(context.BuiltContextKey.HasValue);
        }
        /// <inheritdoc />
        public override bool CanHandle(ISerializableTypeContext context)
        {
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            //We can handle any type technically
            return(true);
        }
        /// <inheritdoc />
        public override bool CanHandle(ISerializableTypeContext context)
        {
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            //We can handle strings. Maybe char[] but that's an odd case.
            return(context.TargetType == typeof(string));
        }
        public static bool HasMemberAttribute <TAttributeType>([NotNull] this ISerializableTypeContext context)
            where TAttributeType : Attribute
        {
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            return(context.MemberMetadata.Any(x => x.GetType() == typeof(TAttributeType)));
        }
        public static ISerializableTypeContext Override([NotNull] this ISerializableTypeContext context, ContextualSerializerLookupKey key)
        {
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            //Deocrate the context to set the provided key
            return(new ContextKeyOverrideDecorator(context, key));
        }
        public ContextKeyOverrideDecorator([NotNull] ISerializableTypeContext context, ContextualSerializerLookupKey key)
        {
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            managedContext = context;

            BuiltContextKey = key;
        }
        public static ISerializableTypeContext Override([NotNull] this ISerializableTypeContext context, [NotNull] Type targetType)
        {
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }
            if (targetType == null)
            {
                throw new ArgumentNullException(nameof(targetType));
            }

            //Decorate the context to override the target type
            return(new ContextTargetOverrideDecorator(context, targetType));
        }
예제 #10
0
        public ContextTargetOverrideDecorator([NotNull] ISerializableTypeContext context, [NotNull] Type targetType)
        {
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }
            if (targetType == null)
            {
                throw new ArgumentNullException(nameof(targetType));
            }

            managedContext = context;
            TargetType     = targetType;
        }
        /// <inheritdoc />
        public override bool CanHandle(ISerializableTypeContext context)
        {
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context), $"Provided argument {nameof(context)} was null.");
            }

            //Check if the type has wirebase type attributes.
            //If it does then the type is complex and can have subtypes coming across the wire
            //Include checking for runtime link information
            return((context.TargetType.GetTypeInfo().GetCustomAttributes <WireDataContractAttribute>(false).Any() && context.TargetType.GetTypeInfo().GetCustomAttribute <WireDataContractAttribute>(false).ExpectRuntimeLink) ||
                   context.TargetType.GetTypeInfo().GetCustomAttributes <WireDataContractBaseTypeAttribute>(false).Any() ||
                   context.TargetType.GetTypeInfo().GetCustomAttribute <WireDataContractBaseTypeByFlagsAttribute>(false) != null);
        }
        public static bool HasContextualTypeMetadata([NotNull] this ISerializableTypeContext context)
        {
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            //If there is no context requirement then there is probably no context metadata or shouldn't be
            if (context.ContextRequirement != SerializationContextRequirement.RequiresContext)
            {
                return(false);
            }

            return(context.TypeMetadata.Any());
        }
예제 #13
0
        /// <summary>
        /// Attempts to produce a decorated serializer for the provided <see cref="ISerializableTypeContext"/>.
        /// </summary>
        /// <param name="context">The context.</param>
        /// <exception cref="InvalidOperationException">Throws if the <see cref="ITypeSerializerStrategy{TType}"/> could not be created.</exception>
        /// <returns>A decorated serializer.</returns>
        public ITypeSerializerStrategy <TType> Create <TType>([NotNull] ISerializableTypeContext context)
        {
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            //Build the contextual key first. We used to do this as one of the last steps but we need
            //to grab the key to check if it already exists.
            context.BuiltContextKey = lookupKeyFactoryService.Create(context);

            if (serializerProviderService.HasSerializerFor(context.BuiltContextKey.Value))
            {
                throw new InvalidOperationException($"Tried to create multiple serializer for already created serialize with Context: {context.ToString()}.");
            }

            //This may look weird but this was done for perf reasons
            //We can't be passing around IEnumerables and ToListing them
            //Otherwise complex types will take seconds to register
            List <ISerializableTypeContext> contexts = new List <ISerializableTypeContext>(200);

            GetAllSubTypeContexts(context, contexts);

            IEnumerable <ISerializableTypeContext> byLikelyRegisteration = contexts
                                                                           .Distinct(new SerializableTypeContextComparer())
                                                                           .ToList();

            //We must register all subcontexts first
            foreach (ISerializableTypeContext subContext in byLikelyRegisteration)
            {
                MethodInfo info = null;

                if (CachedGenericInternalCreateMap.ContainsKey(subContext.TargetType))
                {
                    info = CachedGenericInternalCreateMap[subContext.TargetType];
                }
                else
                {
                    info = (CachedGenericInternalCreateMap[subContext.TargetType] = GetType().GetTypeInfo().GetMethod(nameof(InternalCreate), BindingFlags.NonPublic | BindingFlags.Instance)
                                                                                    .MakeGenericMethod(subContext.TargetType));
                }

                info.Invoke(this, new object[] { subContext });
            }

            //Now that all dependencies in the object graph are registered we can create the requested type
            return(InternalCreate <TType>(context));
        }
        public static TAttributeType GetMemberAttribute <TAttributeType>([NotNull] this ISerializableTypeContext context)
            where TAttributeType : Attribute
        {
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            TAttributeType attri = context.MemberMetadata.FirstOrDefault(x => x.GetType() == typeof(TAttributeType)) as TAttributeType;

            if (attri == null)
            {
                throw new InvalidOperationException($"Requested Attribute Type {typeof(TAttributeType).FullName} was unavailable.");
            }

            return(attri);
        }
        public static ISerializableTypeContext Override([NotNull] this ISerializableTypeContext context, SerializationContextRequirement requirement)
        {
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }
            if (!Enum.IsDefined(typeof(SerializationContextRequirement), requirement))
            {
                throw new ArgumentOutOfRangeException(nameof(requirement), "Value should be defined in the SerializationContextRequirement enum.");
            }

            /*if (!Enum.IsDefined(typeof(SerializationContextRequirement), requirement))
             *      throw new InvalidEnumArgumentException(nameof(requirement), (int) requirement,
             *              typeof(SerializationContextRequirement));*/

            //Deocrate the context to set the provided key
            return(new ContextRequirementOverrideDecorator(context, requirement));
        }
        public ContextRequirementOverrideDecorator([NotNull] ISerializableTypeContext context,
                                                   SerializationContextRequirement requirement)
        {
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            if (!Enum.IsDefined(typeof(SerializationContextRequirement), requirement))
            {
                throw new ArgumentOutOfRangeException(nameof(requirement), "Value should be defined in the SerializationContextRequirement enum.");
            }

            /*if (!Enum.IsDefined(typeof(SerializationContextRequirement), requirement))
             *      throw new InvalidEnumArgumentException(nameof(requirement), (int) requirement,
             *              typeof(SerializationContextRequirement));*/

            managedContext     = context;
            ContextRequirement = requirement;
        }
예제 #17
0
 private void RegisterNewSerializerStrategy(ISerializableTypeContext context, ITypeSerializerStrategy strategy)
 {
     if (strategy.ContextRequirement == SerializationContextRequirement.Contextless)
     {
         StrategyRegistry.RegisterType(context.TargetType, strategy);
     }
     else
     {
         //TODO: Clean this up
         if (context.HasContextualKey())
         {
             //Register the serializer with the context key that was built into the serialization context.
             StrategyRegistry.RegisterType(context.BuiltContextKey.Value.ContextFlags, context.BuiltContextKey.Value.ContextSpecificKey, context.TargetType, strategy);
         }
         else
         {
             throw new InvalidOperationException($"Serializer was created but Type: {context.TargetType} came with no contextual key in the end for a contextful serialization context.");
         }
     }
 }
        //Called as the fallback factory.
        /// <inheritdoc />
        public ITypeSerializerStrategy <TType> Create <TType>([NotNull] ISerializableTypeContext context)
        {
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            //This service acts a the default/fallback factory for serializer creation. If any factory encounters a type
            //inside of a type that it doesn't know about or requires handling outside of its scope it'll broadcast that
            //and we will implement more complex handling here

            ITypeSerializerStrategy <TType> strategy = serializerStrategyFactoryService.Create <TType>(context);

            //The serializer could be null; we should verify it
            if (strategy == null)
            {
                throw new InvalidOperationException($"Failed to create serializer for Type: {context.TargetType} with Context: {context.ToString()}.");
            }

            return(strategy);
        }
예제 #19
0
        private ITypeSerializerStrategy <TType> InternalCreate <TType>([NotNull] ISerializableTypeContext context)
        {
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            //TODO: Refactor this. It's duplicated code
            //We should check if the specified a custom type serializer
            if (typeof(TType).GetTypeInfo().HasAttribute <IncludeCustomTypeSerializerAttribute>())
            {
                IncludeCustomTypeSerializerAttribute attri = typeof(TType).GetTypeInfo().GetCustomAttribute <IncludeCustomTypeSerializerAttribute>();

                if (!typeof(ITypeSerializerStrategy <TType>).GetTypeInfo().IsAssignableFrom(attri.TypeSerializerType))
                {
                    throw new InvalidOperationException($"Specified custom Type Serializer Type: {attri.TypeSerializerType} but did not implement {nameof(ITypeSerializerStrategy<TType>)}. Must implment that interface for custom serializers.");
                }

                ITypeSerializerStrategy <TType> serializer = Activator.CreateInstance(attri.TypeSerializerType) as ITypeSerializerStrategy <TType>;

                this.StrategyRegistry.RegisterType(typeof(TType), serializer);

                return(serializer);
            }


            DecoratorHandler handler = decoratorHandlers.First(h => h.CanHandle(context));

            ITypeSerializerStrategy <TType> strategy = handler.Create <TType>(context);

            if (strategy == null)
            {
                throw new InvalidOperationException($"Couldn't generate a strategy for Type: {context.TargetType} with Context: {context.BuiltContextKey?.ToString()}.");
            }

            //If the serializer is contextless we can register it with the general provider
            RegisterNewSerializerStrategy(context, strategy);

            return(strategy);
        }
예제 #20
0
        private void GetAllSubTypeContexts([NotNull] ISerializableTypeContext context, List <ISerializableTypeContext> knownContexts)
        {
            List <ISerializableTypeContext> contexts = GetUnknownUnregisteredSubTypeContexts(context, knownContexts);

            foreach (ISerializableTypeContext s in contexts)
            {
                s.BuiltContextKey = lookupKeyFactoryService.Create(s);
            }

            //Get only the new contexts
            contexts = contexts.Except(knownContexts, new SerializableTypeContextComparer())
                       .ToList();

            //After we've made context unique ones we haven't registered we NEED to make sure that the ones we know in this stack
            //are included in the knowns we pass to ones below this recurring stack
            knownContexts.AddRange(contexts);

            //If there are any new we need to recurr to get their dependencies
            foreach (var s in contexts)
            {
                //We don't return lists anymore. Just add elements instead to avoid allocations
                GetAllSubTypeContexts(s, knownContexts);
            }
        }
        /// <inheritdoc />
        protected override ITypeSerializerStrategy <TType> TryCreateSerializer <TType>(ISerializableTypeContext context)
        {
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            ITypeSerializerStrategy <TType> complexTypeSerializerDecorator = new ComplexTypeSerializerDecorator <TType>(new MemberSerializationMediatorCollection <TType>(SerializationMediatorFactory), new LambdabasedDeserializationPrototyeFactory <TType>(), serializerProviderService);

            //Check for compression flags
            if (context.BuiltContextKey.Value.ContextFlags.HasFlag(ContextTypeFlags.Compressed))
            {
                complexTypeSerializerDecorator = new CompressionTypeSerializerStrategyDecorator <TType>(complexTypeSerializerDecorator, serializerProviderService.Get <uint>());
            }

            return(complexTypeSerializerDecorator);
        }
 /// <inheritdoc />
 public override bool CanHandle(ISerializableTypeContext context)
 {
     //Right now we can handle only DateTimes as special complex types.
     return(context.TargetType == typeof(DateTime) || context.TargetType == typeof(BitArray));
 }
예제 #23
0
 private List <ISerializableTypeContext> GetUnknownUnregisteredSubTypeContexts([NotNull] ISerializableTypeContext context, IEnumerable <ISerializableTypeContext> knownContexts)
 {
     return(decoratorHandlers.First(h => h.CanHandle(context))
            .GetAssociatedSerializationContexts(context)
            .Select(s =>
     {
         s.BuiltContextKey = lookupKeyFactoryService.Create(s);
         return s;
     })
            .Where(s => !serializerProviderService.HasSerializerFor(s.BuiltContextKey.Value))              //make sure we ignore known registered types
            .Except(knownContexts, new SerializableTypeContextComparer())
            .ToList());
 }
예제 #24
0
        //TODO: Refactor; mess; too long
        /// <inheritdoc />
        protected override ITypeSerializerStrategy <TType> TryCreateSerializer <TType>(ISerializableTypeContext context)
        {
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            if (!context.BuiltContextKey.HasValue)
            {
                throw new InvalidOperationException($"Provided {nameof(ISerializableTypeContext)} did not contain a valid {nameof(context.BuiltContextKey)} for Context: {context.ToString()}.");
            }

            ICollectionSizeStrategy collectionSizeStrategy = null;

            //TODO: Handle contextless requests. The future may require a single array serializer for all unknown sizes.
            if (context.BuiltContextKey.Value.ContextFlags.HasFlag(ContextTypeFlags.FixedSize))
            {
                int knownSize = context.BuiltContextKey.Value.ContextSpecificKey.Key;

                collectionSizeStrategy = new FixedSizeCollectionSizeStrategy(knownSize);
            }
            else if (context.BuiltContextKey.Value.ContextFlags.HasFlag(ContextTypeFlags.SendSize))
            {
                sbyte addedSize = (sbyte)(context.BuiltContextKey.Value.ContextSpecificKey.Key >> 4);
                //TODO: Is there a way to obsecure this bit fiddling?
                switch ((SendSizeAttribute.SizeType)(context.BuiltContextKey.Value.ContextSpecificKey.Key & 0b0000_0000_0000_1111))                 //get just the key
                {
 /// <inheritdoc />
 protected override IEnumerable <ISerializableTypeContext> TryGetAssociatedSerializableContexts(ISerializableTypeContext context)
 {
     //We don't need any special types registered
     return(Enumerable.Empty <ISerializableTypeContext>());
 }
        //TODO: Refactor
        /// <inheritdoc />
        protected override ITypeSerializerStrategy <TType> TryCreateSerializer <TType>(ISerializableTypeContext context)
        {
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            if (typeof(TType) != typeof(string))
            {
                throw new InvalidOperationException($"{nameof(StringSerializerDecoratorHandler)} cannot handle creation of serializer decorators involves {typeof(string).FullName}.");
            }

            if (!context.HasContextualKey())
            {
                throw new ArgumentException($"Provided context {nameof(context)} did not contain a valid {nameof(context.BuiltContextKey)}.");
            }

            if (context.ContextRequirement == SerializationContextRequirement.Contextless)
            {
                return((ITypeSerializerStrategy <TType>)serializerProviderService.Get <string>());               //The caller should know what he's doing.
            }
            //TODO: Throw on invalid metadata combinations
            ITypeSerializerStrategy <string> serializer = null;
            Encoding encoding = Encoding.ASCII;

            if (context.BuiltContextKey.Value.ContextFlags.HasFlag(ContextTypeFlags.Encoding))
            {
                if (context.BuiltContextKey.Value.ContextFlags.HasFlag(ContextTypeFlags.ASCII))
                {
                    encoding   = Encoding.ASCII;
                    serializer = new StringSerializerStrategy(Encoding.ASCII, SerializationContextRequirement.RequiresContext);
                }
                else if (context.BuiltContextKey.Value.ContextFlags.HasFlag(ContextTypeFlags.UTF16))
                {
                    encoding   = Encoding.Unicode;
                    serializer = new StringSerializerStrategy(Encoding.Unicode, SerializationContextRequirement.RequiresContext);
                }
                else if (context.BuiltContextKey.Value.ContextFlags.HasFlag(ContextTypeFlags.UTF32))
                {
                    encoding   = Encoding.UTF32;
                    serializer = new StringSerializerStrategy(Encoding.UTF32, SerializationContextRequirement.RequiresContext);
                }
                else if (context.BuiltContextKey.Value.ContextFlags.HasFlag(ContextTypeFlags.UTF8))
                {
                    encoding   = Encoding.UTF8;
                    serializer = new StringSerializerStrategy(Encoding.UTF8, SerializationContextRequirement.RequiresContext);
                }
                else
                {
                    throw new InvalidOperationException($"String had encoding flags but no specified encoding.");
                }
            }
            else
            {
                //If we have a context, but don't have an encoding context, then we should grab the default that uses ASCII
                serializer = serializerProviderService.Get <string>();
            }


            bool shouldTerminate = !context.BuiltContextKey.Value.ContextFlags.HasFlag(ContextTypeFlags.DontTerminate);

            //If we shouldn't null terminate or if we're using a fixed/known size (meaning we never want to append a null terminator past the size)
            if (!shouldTerminate || context.BuiltContextKey.Value.ContextFlags.HasFlag(ContextTypeFlags.FixedSize))
            {
                serializer = new DontTerminateStringSerializerDecorator(serializer, encoding);
            }

            //It is possible that the WoW protocol expects a fixed-size string that both client and server know the length of
            //This can be seen in the first packet Auth_Challenge: uint8   gamename[4];
            //It can be seen that this field is a fixed length string (byte array)
            if (context.BuiltContextKey.Value.ContextFlags.HasFlag(ContextTypeFlags.FixedSize))
            {
                //read the key. It will have the size
                int size = context.BuiltContextKey.Value.ContextSpecificKey.Key;

                serializer = new SizeStringSerializerDecorator(new FixedSizeStringSizeStrategy(context.BuiltContextKey.Value.ContextSpecificKey.Key), serializer, encoding);
            }
            //It is also possible that the WoW protocol expects a length prefixed string
            else if (context.BuiltContextKey.Value.ContextFlags.HasFlag(ContextTypeFlags.SendSize))
            {
                byte addedSize = (byte)(context.BuiltContextKey.Value.ContextSpecificKey.Key >> 4);
                //This is an odd choice but if they mark it with conflicting metdata maybe we should throw?
                switch ((SendSizeAttribute.SizeType)(context.BuiltContextKey.Value.ContextSpecificKey.Key & 0b0000_0000_0000_1111))
                {
        /// <inheritdoc />
        protected override ITypeSerializerStrategy <TType> TryCreateSerializer <TType>(ISerializableTypeContext context)
        {
            if (context.TargetType == typeof(DateTime))
            {
                return(new PackedDateTimeSerializerStrategyDecorator(serializerProviderService.Get <int>()) as ITypeSerializerStrategy <TType>);
            }

            if (context.TargetType == typeof(BitArray))
            {
                return(new BitArraySerializerStrategyDecorator() as ITypeSerializerStrategy <TType>);
            }

            throw new InvalidOperationException($"Special decorator cannot handle {typeof(TType).FullName}.");
        }
        //TODO: Refactor
        /// <inheritdoc />
        protected override ITypeSerializerStrategy <TType> TryCreateSerializer <TType>(ISerializableTypeContext context)
        {
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            IChildKeyStrategy keyStrategy = null;

            //TODO: Check if we can get this from context?
            //Check the WireDataContract attribute for keysize information
            WireDataContractAttribute contractAttribute = typeof(TType).GetTypeInfo().GetCustomAttribute <WireDataContractAttribute>(false);

            //Build the strategy for child size and value read/write
            switch (contractAttribute.OptionalChildTypeKeySize)
            {
            //TODO: Make it a factory
            case WireDataContractAttribute.KeyType.Byte:
                keyStrategy = new GenericChildKeyStrategy <byte>(contractAttribute.TypeHandling, serializerProviderService.Get <byte>());
                break;

            case WireDataContractAttribute.KeyType.Int32:
                keyStrategy = new GenericChildKeyStrategy <int>(contractAttribute.TypeHandling, serializerProviderService.Get <int>());
                break;

            case WireDataContractAttribute.KeyType.UShort:
                keyStrategy = new GenericChildKeyStrategy <ushort>(contractAttribute.TypeHandling, serializerProviderService.Get <ushort>());
                break;

            case WireDataContractAttribute.KeyType.None:
            default:
                throw new InvalidOperationException($"Encountered Type: {typeof(TType).FullName} that requires child type mapping but has provided {nameof(WireDataContractAttribute.KeyType)} Value: {contractAttribute.OptionalChildTypeKeySize} which is invalid.");
            }

            ITypeSerializerStrategy <TType> strat = null;

            //Depending on if we're flags or key return the right serializer decorator.
            if (typeof(TType).GetTypeInfo().GetCustomAttribute <WireDataContractBaseTypeByFlagsAttribute>(false) == null)
            {
                //Won't be null at this point. Should be a valid strategy. We also don't need to deal with context since there is only EVER 1 serializer of this type per type.
                strat = new SubComplexTypeSerializerDecorator <TType>(new LambdabasedDeserializationPrototyeFactory <TType>(), new MemberSerializationMediatorCollection <TType>(mediatorFactoryService).ToArray(), serializerProviderService, keyStrategy);
            }
            else
            {
                strat = new SubComplexTypeWithFlagsSerializerDecorator <TType>(new LambdabasedDeserializationPrototyeFactory <TType>(), new MemberSerializationMediatorCollection <TType>(mediatorFactoryService).ToArray(), serializerProviderService, keyStrategy);
            }

            //Check for compression flags
            if (context.BuiltContextKey.Value.ContextFlags.HasFlag(ContextTypeFlags.Compressed))
            {
                strat = new CompressionTypeSerializerStrategyDecorator <TType>(strat, serializerProviderService.Get <uint>());
            }

            return(strat);
        }
        protected override IEnumerable <ISerializableTypeContext> TryGetAssociatedSerializableContexts(ISerializableTypeContext context)
        {
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            //We need to include the potential default child type now
            IEnumerable <ISerializableTypeContext> contexts = new TypeMemberParsedTypeContextCollection(context.TargetType);

            contexts = contexts.Concat(context.TargetType.GetTypeInfo().GetCustomAttribute <DefaultChildAttribute>(false) != null ? new ISerializableTypeContext[] { new TypeBasedSerializationContext(context.TargetType.GetTypeInfo().GetCustomAttribute <DefaultChildAttribute>().ChildType) } : Enumerable.Empty <ISerializableTypeContext>());

            //Grab the children from the metadata; return type contexts so the types can be handled (no context is required because the children are their own registerable type
            return(contexts.Concat(GetAssociatedChildren(context.TargetType).Select(t => new TypeBasedSerializationContext(t) as ISerializableTypeContext)));
        }
        /// <inheritdoc />
        protected override IEnumerable <ISerializableTypeContext> TryGetAssociatedSerializableContexts(ISerializableTypeContext context)
        {
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            //We need context when we refer to the members of a Type. They could be marked with metadata that could cause a serializer to be context based

            return(new TypeMemberParsedTypeContextCollection(context.TargetType)
                   .Concat(GetInheritanceHierarchy(context.TargetType).Where(t => t.GetTypeInfo().GetCustomAttribute <WireDataContractAttribute>(false) != null).Select(t => new TypeBasedSerializationContext(t))));
        }