//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);
        }
        public SubComplexTypeWithFlagsSerializerDecorator([NotNull] IDeserializationPrototypeFactory <TBaseType> prototypeGenerator, [NotNull] IEnumerable <IMemberSerializationMediator <TBaseType> > serializationDirections,
                                                          [NotNull] IGeneralSerializerProvider serializerProvider, [NotNull] IChildKeyStrategy childKeyStrategy)
            : base(prototypeGenerator, serializationDirections, serializerProvider)
        {
            if (prototypeGenerator == null)
            {
                throw new ArgumentNullException(nameof(prototypeGenerator));
            }
            if (serializationDirections == null)
            {
                throw new ArgumentNullException(nameof(serializationDirections));
            }
            if (serializerProvider == null)
            {
                throw new ArgumentNullException(nameof(serializerProvider));
            }
            if (childKeyStrategy == null)
            {
                throw new ArgumentNullException(nameof(childKeyStrategy));
            }

            keyStrategy = childKeyStrategy;

            DefaultSerializer = typeof(TBaseType).GetTypeInfo().GetCustomAttribute <DefaultChildAttribute>(false) != null
                                ? serializerProviderService.Get(typeof(TBaseType).GetTypeInfo().GetCustomAttribute <DefaultChildAttribute>(false).ChildType) : null;

            //We no longer reserve 0. Sometimes type information of a child is sent as a 0 in WoW protocol. We can opt for mostly metadata market style interfaces.

            List <ChildKeyPair> pairs = new List <ChildKeyPair>();

            foreach (WireDataContractBaseTypeByFlagsAttribute waf in typeof(TBaseType).GetTypeInfo().GetCustomAttributes <WireDataContractBaseTypeByFlagsAttribute>(false))
            {
                if (!typeof(TBaseType).GetTypeInfo().IsAssignableFrom(waf.ChildType.GetTypeInfo()))
                {
                    throw new InvalidOperationException($"Failed to register Type: {typeof(TBaseType).GetType().FullName} because a provided ChildType: {waf.ChildType.FullName} was not actually a child.");
                }

                //TODO: Maybe add a priority system for flags that may override others?
                pairs.Add(new ChildKeyPair(waf.Flag, serializerProviderService.Get(waf.ChildType)));
            }

            serializers = pairs.ToArray();
        }
Exemple #3
0
        public SubComplexTypeSerializerDecorator([NotNull] IDeserializationPrototypeFactory <TBaseType> prototypeGenerator,
                                                 [NotNull] IEnumerable <IMemberSerializationMediator <TBaseType> > serializationDirections,
                                                 [NotNull] IGeneralSerializerProvider serializerProvider, [NotNull] IChildKeyStrategy childKeyStrategy)
            : base(prototypeGenerator, serializationDirections, serializerProvider)
        {
            if (childKeyStrategy == null)
            {
                throw new ArgumentNullException(nameof(childKeyStrategy),
                                                $"Provided {nameof(IChildKeyStrategy)} used for key read and write is null.");
            }

            keyStrategy     = childKeyStrategy;
            typeToKeyLookup = new Dictionary <Type, int>();
            keyToTypeLookup = new Dictionary <int, Type>();

            DefaultSerializer = typeof(TBaseType).GetTypeInfo().GetCustomAttribute <DefaultChildAttribute>(false) != null
                                ? serializerProviderService.Get(typeof(TBaseType).GetTypeInfo().GetCustomAttribute <DefaultChildAttribute>(false).ChildType)
                                : null;

            //We no longer reserve 0. Sometimes type information of a child is sent as a 0 in WoW protocol. We can opt for mostly metadata marker style interfaces.
            //TODO: Add support for basetype serialization metadata marking.
            foreach (WireDataContractBaseTypeAttribute wa in typeof(TBaseType).GetTypeInfo().GetCustomAttributes <WireDataContractBaseTypeAttribute>(false))
            {
                if (wa.Index == keyStrategy.DefaultKey)
                {
                    throw new InvalidOperationException($"Encountered reserved BaseType Key: {wa.Index} on Type: {wa.ChildType.Name}. This key value is reserved for internal handling.");
                }

                RegisterPair(wa.ChildType, wa.Index);
            }

            //If we're not abstract we may be asked to serialize ourselves
            if (!typeof(TBaseType).GetTypeInfo().IsAbstract)
            {
                InternallyManagedComplexSerializer = new ComplexTypeSerializerDecorator <TBaseType>(serializationDirections, prototypeGenerator, serializerProvider);
            }
        }