public PolymorphicComplexBuilder(Type type, SerializerState state)
        {
            _typeDescriptionsByHashCode = new AdaptiveHashtable <TypeDescriptionWithIndex>();
            var typeDescriptions = new Dictionary <int, TypeDescriptionWithIndex>();

            foreach (var description in state.GetDescriptionsForDerivedTypes(type))
            {
                _typeDescriptionsByHashCode.AddValue(
                    (uint)RuntimeHelpers.GetHashCode(description.Type),
                    new TypeDescriptionWithIndex
                {
                    Description = description
                });

                if (!typeDescriptions.ContainsKey(description.Type.GetHashCode()))
                {
                    typeDescriptions.Add(description.Type.GetHashCode(), new TypeDescriptionWithIndex
                    {
                        Description = description
                    });
                }
            }
            _typeDescriptionsByIndex = new TypeDescription[typeDescriptions.Count];
            var index = (byte)0;

            foreach (var item in typeDescriptions)
            {
                item.Value.Index = index;
                var val = _typeDescriptionsByHashCode.TryGetValue((uint)RuntimeHelpers.GetHashCode(item.Value.Description.Type));
                Debug.Assert(val != null, "Type should exist in the type descriptions hash");
                val.Index = index;
                _typeDescriptionsByIndex[index++] = item.Value.Description;
            }
        }
Example #2
0
        internal static MemberSerializerBuilder GetBuilder(Type type, TypeDescription nestedTypeDescription, SerializerState state)
        {
            var serializerBuilder = default(MemberSerializerBuilder);

            if (type.IsBuiltInType())
            {
                var nullableUnderlyingType = Nullable.GetUnderlyingType(type);
                if (nullableUnderlyingType != null)
                {
                    if (nullableUnderlyingType.IsBuiltInType())
                    {
                        serializerBuilder = CreateBuilder(typeof(PrimitiveNullableBuilder <>), nullableUnderlyingType, nullableUnderlyingType);
                    }
                    else
                    {
                        serializerBuilder = CreateBuilder(typeof(ComplexNullableBuilder <>), nullableUnderlyingType, nullableUnderlyingType, state);
                    }
                }
                else
                {
                    if (PrimitiveBuilders.TryGetValue(type, out serializerBuilder))
                    {
                        return(serializerBuilder);
                    }
                    type.TypeNotSupported(type);
                }
            }
            else
            {
                if (type.GetTypeInfo().IsEnum)
                {
                    serializerBuilder = CreateBuilder(typeof(EnumBuilder <>), type, type, Enum.GetUnderlyingType(type));
                }
                else if (type.IsDictionaryType())
                {
                    var dictTypes = type.GetDictionaryArguments();
                    Debug.Assert(dictTypes != null, "Dictionary generic types can't be null for a dictionary");
                    Debug.Assert(state != null, "State can't be null");
                    serializerBuilder = CreateBuilder(
                        typeof(DictionaryBuilder <, ,>),
                        new[] { type, dictTypes.Item1, dictTypes.Item2 },
                        type,
                        dictTypes.Item1,
                        dictTypes.Item2,
                        GetTypeDescription(dictTypes.Item1, state),
                        GetTypeDescription(dictTypes.Item2, state),
                        state);
                }
                else if (type.IsEnumerableType())
                {
                    var baseElementType = type.GetEnumerableArgument();
                    Debug.Assert(baseElementType != null, "Element generic type can't be null for an enumerable");
                    Debug.Assert(state != null, "State can't be null");
                    serializerBuilder = CreateBuilder(
                        typeof(EnumerableBuilder <,>),
                        new[] { type, baseElementType },
                        type,
                        baseElementType,
                        GetTypeDescription(baseElementType, state),
                        state);
                }
                else if (type.GetTypeInfo().IsInterface || type.GetTypeInfo().IsAbstract)
                {
                    var derivedTypes = state.GetDescriptionsForDerivedTypes(type);
                    if (!derivedTypes.Any())
                    {
                        type.NoImplementationsFound(type);
                    }

                    if (derivedTypes.Count() > 1)
                    {
                        serializerBuilder = CreateBuilder(typeof(PolymorphicComplexBuilder <>), type, type, state);
                    }
                    else
                    {
                        serializerBuilder = CreateBuilder(typeof(ComplexBuilder <>), derivedTypes.First().Type, derivedTypes.First());
                        serializerBuilder = WrapWithCheckNullBuilder(type, serializerBuilder);
                    }
                }
                else if (nestedTypeDescription != null)
                {
                    var derivedTypes = state.GetDescriptionsForDerivedTypes(type);
                    if (derivedTypes.Count() > 1)
                    {
                        serializerBuilder = CreateBuilder(typeof(PolymorphicComplexBuilder <>), type, type, state);
                    }
                    else
                    {
                        serializerBuilder = CreateBuilder(typeof(ComplexBuilder <>), type, nestedTypeDescription);
                        if (!type.GetTypeInfo().IsValueType)
                        {
                            serializerBuilder = WrapWithCheckNullBuilder(type, serializerBuilder);
                        }
                    }
                }
                else
                {
                    type.TypeNotSupported(type);
                }
            }
            return(serializerBuilder);
        }