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