/// <summary> /// Gets the external object serializer for the specified type. /// </summary> /// <param name="type">Type to get an external object serializer for.</param> /// <param name="version">Receives the version of the serializer.</param> /// <returns> /// The external object serializer for the specified type; /// <c>null</c>, if the type does not have an external object serializer. /// </returns> public static IExternalObjectSerializer GetExternalObjectSerializer(Type type, out uint version) { // check whether a serializer for exactly the specified type is available if (sExternalObjectSerializerInfoBySerializee.TryGetValue(type, out var eosi)) { version = eosi.SerializerInfo.Version; return(eosi.Serializer); } // there is no external object serializer instance handling the specified type, yet // => find the external object serializer matching best... lock (sSync) { // once again, check whether a serializer for exactly the specified type is available // (maybe someone else has added the serializer meanwhile...) if (sExternalObjectSerializerInfoBySerializee.TryGetValue(type, out eosi)) { version = eosi.SerializerInfo.Version; return(eosi.Serializer); } // get a list containing the serializee type and all interfaces it implements var possibleSerializeeTypes = GetPossibleSerializeeTypes(type); // check the types against the types registered external object serializers can handle // (the order of both lists ensures that the most specific types are checked first) foreach (var possibleSerializeeType in possibleSerializeeTypes) { foreach (var eosInfo in sRegisteredExternalObjectSerializers) { IExternalObjectSerializer eosInstance = null; if (possibleSerializeeType == eosInfo.SerializeeType) { // the serializee exactly matches the serializee supported by the external object serializer // => the serializer can handle the type directly eosInstance = (IExternalObjectSerializer)FastActivator.CreateInstance(eosInfo.SerializerType); } else if (possibleSerializeeType.IsConstructedGenericType && eosInfo.SerializeeType.ContainsGenericParameters) { // the serializee is a generic type and the serializee supported by the external object serializer is a generic type as well // => check whether their generic type definitions are the same, so the serializer can be used to handle the type var possibleSerializeeTypeDefinition = possibleSerializeeType.GetGenericTypeDefinition(); var eosSerializeeTypeDefinition = eosInfo.SerializeeType.GetGenericTypeDefinition(); if (possibleSerializeeTypeDefinition == eosSerializeeTypeDefinition) { // both generic type definitions are the same // => found serializer that can handle the type var constructedEosType = eosInfo.SerializerType.MakeGenericType(possibleSerializeeType.GenericTypeArguments); eosInstance = (IExternalObjectSerializer)FastActivator.CreateInstance(constructedEosType); } } if (eosInstance != null) { // found an external object serializer that is capable of handling the specified type // => add it to the serializer cache... var eosDictCopy = new TypeKeyedDictionary <SerializeeInfo>(sExternalObjectSerializerInfoBySerializee) { { type, new SerializeeInfo(type, eosInfo, eosInstance) } }; Thread.MemoryBarrier(); sExternalObjectSerializerInfoBySerializee = eosDictCopy; version = eosInfo.Version; return(eosInstance); } } } } version = 0; return(null); }
/// <summary> /// Openes a base archive and calls the serializer of the specified type (for base class serialization). /// </summary> /// <param name="obj">Object to serialize.</param> /// <param name="type">Type of the base class to serialize.</param> /// <param name="context">Context object to pass to the serializer of the base class.</param> /// <exception cref="ArgumentException">Specified type is not serializable.</exception> public void WriteBaseArchive(object obj, Type type, object context = null) { CloseArchiveStream(); // ensure the specified type is the type of the specified object or the type of one of its base classes if (obj.GetType().IsAssignableFrom(type)) { throw new ArgumentException("Specified type is neither the type of the specified object nor the type of one of its base classes.", "obj,type"); } // try external object serializer uint version; IExternalObjectSerializer eos = Serializer.GetExternalObjectSerializer(type, out version); if (eos != null) { // consider serializer version overrides... uint versionOverride; if (mSerializer.GetSerializerVersionOverride(type, out versionOverride)) { version = versionOverride; } // write base archive header byte[] buffer = mSerializer.mTempBuffer_Buffer; buffer[0] = (byte)PayloadType.BaseArchiveStart; int count = Leb128EncodingHelper.Write(buffer, 1, version); mStream.Write(buffer, 0, 1 + count); // serialize object SerializerArchive archive = new SerializerArchive(mSerializer, mStream, type, version, context); eos.Serialize(archive, version, obj); archive.Close(); return; } // try internal object serializer IInternalObjectSerializer ios = Serializer.GetInternalObjectSerializer(obj, type, out version); if (ios != null) { // consider serializer version overrides... uint versionOverride; if (mSerializer.GetSerializerVersionOverride(type, out versionOverride)) { version = versionOverride; } // write base archive header byte[] buffer = mSerializer.mTempBuffer_Buffer; buffer[0] = (byte)PayloadType.BaseArchiveStart; int count = Leb128EncodingHelper.Write(buffer, 1, version); mStream.Write(buffer, 0, 1 + count); // call the Serialize() method of the base class SerializerArchive archive = new SerializerArchive(mSerializer, mStream, type, version, context); Serializer.IosSerializeDelegate serializeDelegate = Serializer.GetInternalObjectSerializerSerializeCaller(type); serializeDelegate(ios, archive, version); archive.Close(); return; } // specified type is not serializable... string error = string.Format("Specified type ({0}) is not serializable.", type.FullName); throw new ArgumentException(error, nameof(type)); }
/// <summary> /// Initializes a new instance of the <see cref="SerializeeInfo"/> class. /// </summary> /// <param name="serializeeType">Type of the serializee.</param> /// <param name="serializerInfo">Information about the serializer handling the serializee.</param> /// <param name="serializer">The external object serializer instance.</param> public SerializeeInfo(Type serializeeType, SerializerInfo serializerInfo, IExternalObjectSerializer serializer) { SerializeeType = serializeeType; SerializerInfo = serializerInfo; Serializer = serializer; }
/// <summary> /// Intializes a new instance of the <see cref="ExternalObjectSerializerInfo"/> class. /// </summary> /// <param name="serializer">External object serializer.</param> /// <param name="version">Version of the external object serializer.</param> public ExternalObjectSerializerInfo(IExternalObjectSerializer serializer, uint version) { Serializer = serializer; Version = version; }