Пример #1
0
        /// <summary>
        /// Creates and registers a handler for the specified type according to the rules added so far.
        /// </summary>
        /// <typeparam name="T">The type being serialized.</typeparam>
        /// <returns>The newly created handler.</returns>
        private SerializationHandler AddHandler <T>()
        {
            SerializationHandler handler = null;
            var             type         = typeof(T);
            ISerializer <T> serializer   = null;
            TypeSchema      schema       = null;

            if (!this.knownNames.TryGetValue(type, out string name))
            {
                name = TypeSchema.GetContractName(type, this.runtimeVersion);
            }

            int id = this.schemas.TryGetValue(name, out schema) ? schema.Id : TypeSchema.GetId(name);

            serializer = this.CreateSerializer <T>();
            handler    = SerializationHandler.Create <T>(serializer, name, id);

            // first register the handler
            int oldCount    = this.handlers.Length;
            var newHandlers = new SerializationHandler[oldCount + 1];

            Array.Copy(this.handlers, newHandlers, oldCount);
            newHandlers[oldCount] = handler;
            this.handlers         = newHandlers;

            var newIndex = new Dictionary <SerializationHandler, int>(this.index);

            newIndex[handler] = oldCount;
            this.index        = newIndex;

            var newHandlersByType = new Dictionary <Type, SerializationHandler>(this.handlersByType);

            newHandlersByType[type] = handler;
            this.handlersByType     = newHandlersByType;

            var newHandlersById = new Dictionary <int, SerializationHandler>(this.handlersById);

            newHandlersById[handler.Id] = handler;
            this.handlersById           = newHandlersById;

            // find the schema for this serializer (can be null for interfaces)
            if (serializer != null)
            {
                // initialize the serializer after the handler is registered,
                // to make sure all handlers are registered before initialization runs and
                // allow the serializer initialization code to find and cache the handlers for the types it needs
                schema = serializer.Initialize(this, schema);

                // let any subscribers know that we initialized a new serializer that publishes a schema
                if (schema != null)
                {
                    // store the updated schema and override whatever is present already
                    this.schemas[schema.Name]   = schema;
                    this.schemasById[schema.Id] = schema;
                    this.SchemaAdded?.Invoke(this, schema);
                }
            }

            return(handler);
        }
Пример #2
0
        /// <summary>
        /// Creates and registers a handler for the specified type according to the rules added so far.
        /// </summary>
        /// <typeparam name="T">The type being serialized.</typeparam>
        /// <returns>The newly created handler.</returns>
        private SerializationHandler AddHandler <T>()
        {
            SerializationHandler handler = null;
            var             type         = typeof(T);
            ISerializer <T> serializer   = null;
            TypeSchema      schema       = null;

            if (!this.knownNames.TryGetValue(type, out string name))
            {
                name = TypeSchema.GetContractName(type, this.runtimeVersion);
            }

            if (!this.schemas.TryGetValue(name, out schema))
            {
                // try to match to an existing schema without assembly/version info
                string typeName = TypeResolutionHelper.RemoveAssemblyName(type.AssemblyQualifiedName);
                schema = this.schemas.Values.FirstOrDefault(s => TypeResolutionHelper.RemoveAssemblyName(s.TypeName) == typeName);
            }

            int id = schema?.Id ?? TypeSchema.GetId(name);

            serializer = this.CreateSerializer <T>();
            handler    = SerializationHandler.Create <T>(serializer, schema?.Name ?? name, id);

            // first register the handler
            int oldCount    = this.handlers.Length;
            var newHandlers = new SerializationHandler[oldCount + 1];

            Array.Copy(this.handlers, newHandlers, oldCount);
            newHandlers[oldCount] = handler;
            this.handlers         = newHandlers;

            var newIndex = new Dictionary <SerializationHandler, int>(this.index);

            newIndex[handler] = oldCount;
            this.index        = newIndex;

            var newHandlersByType = new Dictionary <Type, SerializationHandler>(this.handlersByType);

            newHandlersByType[type] = handler;
            this.handlersByType     = newHandlersByType;

            var newHandlersById = new Dictionary <int, SerializationHandler>(this.handlersById);

            newHandlersById[handler.Id] = handler;
            this.handlersById           = newHandlersById;

            // find the schema for this serializer (can be null for interfaces)
            if (serializer != null)
            {
                // initialize the serializer after the handler is registered,
                // to make sure all handlers are registered before initialization runs and
                // allow the serializer initialization code to find and cache the handlers for the types it needs
                try
                {
                    schema = serializer.Initialize(this, schema);

                    // let any subscribers know that we initialized a new serializer that publishes a schema
                    if (schema != null)
                    {
                        // store the updated schema and override whatever is present already
                        this.schemas[schema.Name]   = schema;
                        this.schemasById[schema.Id] = schema;
                        this.SchemaAdded?.Invoke(this, schema);
                    }
                }
                catch (SerializationException)
                {
                    // Even though we're going to rethrow this exception, some callers may wish to
                    // attempt to recover from this error and just mark this one stream type as
                    // unreadable. So we should remove the handler we just registered as it's not
                    // yet properly initialized.
                    oldCount    = this.handlers.Length;
                    newHandlers = new SerializationHandler[oldCount - 1];
                    Array.Copy(this.handlers, newHandlers, oldCount - 1);
                    this.handlers = newHandlers;

                    newIndex = new Dictionary <SerializationHandler, int>(this.index);
                    newIndex.Remove(handler);
                    this.index = newIndex;

                    newHandlersByType = new Dictionary <Type, SerializationHandler>(this.handlersByType);
                    newHandlersByType.Remove(type);
                    this.handlersByType = newHandlersByType;

                    newHandlersById = new Dictionary <int, SerializationHandler>(this.handlersById);
                    newHandlersById.Remove(handler.Id);
                    this.handlersById = newHandlersById;

                    throw;
                }
            }

            return(handler);
        }