예제 #1
0
        /// <summary>
        /// Attempts to produce a decorated serializer for the provided <see cref="ISerializableTypeContext"/>.
        /// </summary>
        /// <param name="context">The context.</param>
        /// <exception cref="InvalidOperationException">Throws if the <see cref="ITypeSerializerStrategy{TType}"/> could not be created.</exception>
        /// <returns>A decorated serializer.</returns>
        public ITypeSerializerStrategy <TType> Create <TType>([NotNull] ISerializableTypeContext context)
        {
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            //Build the contextual key first. We used to do this as one of the last steps but we need
            //to grab the key to check if it already exists.
            context.BuiltContextKey = lookupKeyFactoryService.Create(context);

            if (serializerProviderService.HasSerializerFor(context.BuiltContextKey.Value))
            {
                throw new InvalidOperationException($"Tried to create multiple serializer for already created serialize with Context: {context.ToString()}.");
            }

            //This may look weird but this was done for perf reasons
            //We can't be passing around IEnumerables and ToListing them
            //Otherwise complex types will take seconds to register
            List <ISerializableTypeContext> contexts = new List <ISerializableTypeContext>(200);

            GetAllSubTypeContexts(context, contexts);

            IEnumerable <ISerializableTypeContext> byLikelyRegisteration = contexts
                                                                           .Distinct(new SerializableTypeContextComparer())
                                                                           .ToList();

            //We must register all subcontexts first
            foreach (ISerializableTypeContext subContext in byLikelyRegisteration)
            {
                MethodInfo info = null;

                if (CachedGenericInternalCreateMap.ContainsKey(subContext.TargetType))
                {
                    info = CachedGenericInternalCreateMap[subContext.TargetType];
                }
                else
                {
                    info = (CachedGenericInternalCreateMap[subContext.TargetType] = GetType().GetTypeInfo().GetMethod(nameof(InternalCreate), BindingFlags.NonPublic | BindingFlags.Instance)
                                                                                    .MakeGenericMethod(subContext.TargetType));
                }

                info.Invoke(this, new object[] { subContext });
            }

            //Now that all dependencies in the object graph are registered we can create the requested type
            return(InternalCreate <TType>(context));
        }
예제 #2
0
        public ITypeSerializerStrategy <TType> Create <TType>([NotNull] ISerializableTypeContext context)
        {
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            if (!CanHandle(context))
            {
                throw new InvalidOperationException($"Cannot handle Type: {context.TargetType.Name} with a {this.GetType().FullName}.");
            }

            if (!context.BuiltContextKey.HasValue)
            {
                throw new InvalidOperationException($"Failed to build a {nameof(ContextualSerializerLookupKey)} for the Type: {context.TargetType} with Context: {context.ToString()}.");
            }

            ITypeSerializerStrategy <TType> serializer = TryCreateSerializer <TType>(context);

            if (serializer == null)
            {
                throw new InvalidOperationException($"Failed to generate a serializer for Type: {context.TargetType.Name} with decorator factory {this.GetType().FullName}.");
            }

            return(serializer);
        }
예제 #3
0
        //TODO: Refactor; mess; too long
        /// <inheritdoc />
        protected override ITypeSerializerStrategy <TType> TryCreateSerializer <TType>(ISerializableTypeContext context)
        {
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            if (!context.BuiltContextKey.HasValue)
            {
                throw new InvalidOperationException($"Provided {nameof(ISerializableTypeContext)} did not contain a valid {nameof(context.BuiltContextKey)} for Context: {context.ToString()}.");
            }

            ICollectionSizeStrategy collectionSizeStrategy = null;

            //TODO: Handle contextless requests. The future may require a single array serializer for all unknown sizes.
            if (context.BuiltContextKey.Value.ContextFlags.HasFlag(ContextTypeFlags.FixedSize))
            {
                int knownSize = context.BuiltContextKey.Value.ContextSpecificKey.Key;

                collectionSizeStrategy = new FixedSizeCollectionSizeStrategy(knownSize);
            }
            else if (context.BuiltContextKey.Value.ContextFlags.HasFlag(ContextTypeFlags.SendSize))
            {
                sbyte addedSize = (sbyte)(context.BuiltContextKey.Value.ContextSpecificKey.Key >> 4);
                //TODO: Is there a way to obsecure this bit fiddling?
                switch ((SendSizeAttribute.SizeType)(context.BuiltContextKey.Value.ContextSpecificKey.Key & 0b0000_0000_0000_1111))                 //get just the key
                {
        //Called as the fallback factory.
        /// <inheritdoc />
        public ITypeSerializerStrategy <TType> Create <TType>([NotNull] ISerializableTypeContext context)
        {
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            //This service acts a the default/fallback factory for serializer creation. If any factory encounters a type
            //inside of a type that it doesn't know about or requires handling outside of its scope it'll broadcast that
            //and we will implement more complex handling here

            ITypeSerializerStrategy <TType> strategy = serializerStrategyFactoryService.Create <TType>(context);

            //The serializer could be null; we should verify it
            if (strategy == null)
            {
                throw new InvalidOperationException($"Failed to create serializer for Type: {context.TargetType} with Context: {context.ToString()}.");
            }

            return(strategy);
        }