internal static void CreateDataExtensionProperty(
            ref ReadStack state,
            object obj,
            BinaryPropertyInfo binaryPropertyInfo)
        {
            Debug.Assert(binaryPropertyInfo != null);

            object extensionData = binaryPropertyInfo.GetValueAsObject(obj);

            if (extensionData == null)
            {
                // Create the appropriate dictionary type. We already verified the types.
#if DEBUG
                Type   underlyingIDictionaryType = binaryPropertyInfo.DeclaredPropertyType.GetCompatibleGenericInterface(typeof(IDictionary <,>)) !;
                Type[] genericArgs = underlyingIDictionaryType.GetGenericArguments();

                Debug.Assert(underlyingIDictionaryType.IsGenericType);
                Debug.Assert(genericArgs.Length == 2);
                Debug.Assert(genericArgs[0].UnderlyingSystemType == typeof(string));
                Debug.Assert(
                    genericArgs[1].UnderlyingSystemType == BinaryClassInfo.ObjectType);
#endif
                if (binaryPropertyInfo.RuntimeClassInfo.CreateObject == null)
                {
                    ThrowHelper.ThrowNotSupportedException_SerializationNotSupported(binaryPropertyInfo.DeclaredPropertyType);
                }

                extensionData = binaryPropertyInfo.RuntimeClassInfo.CreateObject();
                binaryPropertyInfo.SetExtensionDictionaryAsObject(ref state, obj, extensionData);
            }

            // We don't add the value to the dictionary here because we need to support the read-ahead functionality for Streams.
        }
        internal void ResolveTypes(BinarySerializerOptions options, Type returnType)
        {
            Options = options;
            if (options.TypeHandler != null)
            {
                TypeResolver = options.TypeHandler.CreateResolver();
            }
            else
            {
                TypeResolver = TypeHandler.DefaultTypeResolver;
            }

            TypeMap.ResolveTypes(TypeResolver);

            PrimaryType = TypeMap.GetType(PrimaryTypeSeq);


            if (PrimaryType != null)
            {
                if (PrimaryType.IsClass && !returnType.IsAssignableFrom(PrimaryType))
                {
                    PrimaryType = returnType;
                }
            }
            else
            {
                PrimaryType = returnType;
            }

            if (PrimaryType.IsInterface || PrimaryType.IsAbstract)
            {
                ThrowHelper.ThrowNotSupportedException_SerializationNotSupported(PrimaryType);
            }
        }
        public BinaryClassInfo([NotNull] Type type, [NotNull] TypeMap typeMap, [NotNull] BinarySerializerOptions options)
        {
            TypeMap = typeMap;
            Type    = type;
            Options = options;

            BinaryConverter converter = GetConverter(
                Type,
                parentClassType: null, // A ClassInfo never has a "parent" class.
                memberInfo: null,      // A ClassInfo never has a "parent" property.
                out Type runtimeType,
                Options);

            ClassType = converter.ClassType;

            PropertyInfoForClassInfo = CreatePropertyInfoForClassInfo(TypeMap, Type, runtimeType, converter, Options);
            TypeSeq = converter.GetTypeSeq(typeMap, options);

            switch (ClassType)
            {
            case ClassType.Object:
            {
                CreateObject = Options.MemberAccessorStrategy.CreateConstructor(type);
                GetObjectMemberInfos(type, typeMap, converter);
            }
            break;

            case ClassType.Enumerable:
            case ClassType.Dictionary:
            {
                ElementType  = converter.ElementType;
                CreateObject = Options.MemberAccessorStrategy.CreateConstructor(runtimeType);
                GetObjectMemberInfos(type, typeMap, converter, true);
            }
            break;

            case ClassType.Value:
            case ClassType.NewValue:
            {
                CreateObject = Options.MemberAccessorStrategy.CreateConstructor(type);
            }
            break;

            case ClassType.None:
            {
                ThrowHelper.ThrowNotSupportedException_SerializationNotSupported(type);
            }
            break;

            default:
                Debug.Fail($"Unexpected class type: {ClassType}");
                throw new InvalidOperationException();
            }
        }