//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(); }
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); } }