Det är ett par saker på gång. Det viktigaste är att du måste konsumera indata oavsett typ, annars blir deserialiseringsprocessen ur synk. Jag har testat ditt scenario genom att skriva en anpassad serializer som heter ZipCodeSerializer som hanterar nollvärden och skriver postkoder som strängar, men accepterar antingen sträng eller ints på inmatning och konverterar ints till sträng.
Jag använde den här klassen för att testa:
public class Address
{
public ObjectId Id;
public string ZipCode;
}
Och det här är den anpassade serialiseraren jag skrev:
public class ZipCodeSerializer : BsonBaseSerializer
{
public override object Deserialize(BsonReader bsonReader, Type nominalType, Type actualType, IBsonSerializationOptions options)
{
var bsonType = bsonReader.CurrentBsonType;
switch (bsonType)
{
case BsonType.Null:
bsonReader.ReadNull();
return null;
case BsonType.String:
return bsonReader.ReadString();
case BsonType.Int32:
return bsonReader.ReadInt32().ToString();
default:
var message = string.Format("ZipCodeSerializer expects to find a String or an Int32, not a {0}.", bsonType);
throw new BsonSerializationException(message);
}
}
public override void Serialize(BsonWriter bsonWriter, Type nominalType, object value, IBsonSerializationOptions options)
{
if (value == null)
{
bsonWriter.WriteNull();
}
else
{
bsonWriter.WriteString((string)value);
}
}
}
Du måste se till att den anpassade serializern är ansluten, vilket du kan göra så här:
BsonClassMap.RegisterClassMap<Address>(cm =>
{
cm.AutoMap();
cm.GetMemberMap(a => a.ZipCode).SetSerializer(new ZipCodeSerializer());
});
Så nu kommer postkodfältet för klassen Adress att hanteras av den anpassade serializern.
Jag skapade en del testdata med BsonDocument för att göra det enkelt att tvinga fram särskilda lagrade versioner av data i min testsamling:
collection.Drop();
collection.Insert(new BsonDocument());
collection.Insert(new BsonDocument("ZipCode", BsonNull.Value));
collection.Insert(new BsonDocument("ZipCode", "12345"));
collection.Insert(new BsonDocument("ZipCode", 56789));
Så här såg dokumenten ut med mongoskalet:
> db.test.find()
{ "_id" : ObjectId("4f871374e447ad238040e346") }
{ "_id" : ObjectId("4f871374e447ad238040e347"), "ZipCode" : null }
{ "_id" : ObjectId("4f871374e447ad238040e348"), "ZipCode" : "12345" }
{ "_id" : ObjectId("4f871374e447ad238040e349"), "ZipCode" : 56789 }
>
så vi ser att vissa postkoder är strängar och vissa är ints (det finns också en noll).
Och det här är min testkod:
foreach (var document in collection.FindAll())
{
Console.WriteLine(document.ToJson());
}
Och resultatet av att köra testkoden är:
{ "_id" : ObjectId("4f871374e447ad238040e346"), "ZipCode" : null }
{ "_id" : ObjectId("4f871374e447ad238040e347"), "ZipCode" : null }
{ "_id" : ObjectId("4f871374e447ad238040e348"), "ZipCode" : "12345" }
{ "_id" : ObjectId("4f871374e447ad238040e349"), "ZipCode" : "56789" }
Press Enter to continue
Lägg märke till att postnumret som var en int i databasen nu är en sträng.
Hela källkoden för mitt testprogram finns på: