Esempio n. 1
0
        /// <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);
        }
Esempio n. 2
0
        /// <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));
        }
Esempio n. 3
0
 /// <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;
 }
Esempio n. 4
0
 /// <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;
 }