/// <summary> /// Looks up the actual type of an object to be deserialized. /// </summary> /// <param name="nominalType">The nominal type of the object.</param> /// <param name="discriminator">The discriminator.</param> /// <returns>The actual type of the object.</returns> public static Type LookupActualType(Type nominalType, BsonValue discriminator) { if (discriminator == null) { return(nominalType); } // note: EnsureKnownTypesAreRegistered handles its own locking so call from outside any lock EnsureKnownTypesAreRegistered(nominalType); __configLock.EnterReadLock(); try { Type actualType = null; HashSet <Type> hashSet; if (__discriminators.TryGetValue(discriminator, out hashSet)) { foreach (var type in hashSet) { if (nominalType.IsAssignableFrom(type)) { if (actualType == null) { actualType = type; } else { string message = string.Format("Ambiguous discriminator '{0}'.", discriminator); throw new BsonSerializationException(message); } } } } if (actualType == null && discriminator.IsString) { actualType = TypeNameDiscriminator.GetActualType(discriminator.AsString); // see if it's a Type name } if (actualType == null) { string message = string.Format("Unknown discriminator value '{0}'.", discriminator); throw new BsonSerializationException(message); } if (!nominalType.IsAssignableFrom(actualType)) { string message = string.Format( "Actual type {0} is not assignable to expected type {1}.", actualType.FullName, nominalType.FullName); throw new BsonSerializationException(message); } return(actualType); } finally { __configLock.ExitReadLock(); } }