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