Example #1
0
        /// <inheritdoc/>
        public virtual bool Deserialize(IParser reader, Type expectedType, Func <IParser, Type, object> nestedObjectDeserializer, out object value)
        {
            value = null;
            if (!reader.Accept(out MappingStart mapping))
            {
                return(false);
            }
            if (expectedType.IsInterface ||
                !expectedType.IsAbstract ||
                !expectedType.TryGetCustomAttribute(out DiscriminatorAttribute discriminatorAttribute))
            {
                return(this.Inner.Deserialize(reader, expectedType, nestedObjectDeserializer, out value));
            }
            if (!this.Resolvers.TryGetValue(expectedType, out AbstractTypeResolver resolver))
            {
                resolver = new AbstractTypeResolver(expectedType);
                this.Resolvers.Add(expectedType, resolver);
            }
            ParsingEventStream stream = ParsingEventStream.Create(reader);

            if (!resolver.TryResolve(stream, out Type concreteType))
            {
                throw new NullReferenceException($"Failed to resolve the concrete type for the abstract type '{expectedType.Name}'");
            }
            stream.Reset();
            return(this.Inner.Deserialize(stream, concreteType, nestedObjectDeserializer, out value));
        }
Example #2
0
        /// <summary>
        /// Attempts to find the specified mapping entry
        /// </summary>
        /// <param name="parser">The <see cref="ParsingEventStream"/> to search</param>
        /// <param name="selector">A predicate <see cref="Func{T, TResult}"/> used to search the <see cref="ParsingEventStream"/> for a specific <see cref="ParsingEvent"/></param>
        /// <param name="key">The key of the matching <see cref="Scalar"/></param>
        /// <param name="value">The matching <see cref="Scalar"/>'s <see cref="ParsingEvent"/> </param>
        /// <returns>A boolean indicating whether or not the specified mapping entry could be found</returns>
        public static bool TryFindMappingEntry(this ParsingEventStream parser, Func <Scalar, bool> selector, out Scalar key, out ParsingEvent value)
        {
            parser.Consume <MappingStart>();
            do
            {
                switch (parser.Current)
                {
                case Scalar scalar:
                    var keyMatched = selector(scalar);
                    parser.MoveNext();
                    if (keyMatched)
                    {
                        value = parser.Current;
                        key   = scalar;
                        return(true);
                    }
                    parser.SkipThisAndNestedEvents();
                    break;

                case MappingStart or SequenceStart:
                    parser.SkipThisAndNestedEvents();
                    break;

                default:
                    parser.MoveNext();
                    break;
                }
            }while (parser.Current is not null);
            key   = null;
            value = null;
            return(false);
        }
Example #3
0
 /// <summary>
 /// Attempts to resolve the abstract type's implementation based on the specified <see cref="ParsingEventStream"/>
 /// </summary>
 /// <param name="stream">The <see cref="ParsingEventStream"/> to use to resolve the implementation type</param>
 /// <param name="implementationType">The resulting implementation type</param>
 /// <returns>A boolean indicating whether or not the implementation type could be resolved thanks to the specified <see cref="ParsingEventStream"/></returns>
 public bool TryResolve(ParsingEventStream stream, out Type implementationType)
 {
     implementationType = null;
     if (stream.TryFindMappingEntry(scalar =>
     {
         return(string.Equals(scalar.Value, this.DiscriminatorProperty.Name, StringComparison.InvariantCultureIgnoreCase));
     }, out Scalar key, out ParsingEvent value))
     {
         if (value is Scalar valueScalar)
         {
             return(this.TypeMappings.TryGetValue(valueScalar.Value.ToLower(), out implementationType));
         }
     }
     return(false);
 }