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