[CSHARP-75] Deserialization discriminators are too lazy Created: 19/Oct/10  Updated: 19/Oct/16  Resolved: 20/Oct/10

Status: Closed
Project: C# Driver
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Bug Priority: Critical - P2
Reporter: Justin Dearing Assignee: Robert Stam
Resolution: Done Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified


 Description   

Long story short, this works:
Foo ret = new Foo();
Trace.TraceInformation("Doing stuff to

{0}

.", ret.ToJson());
ret = collection.FindOneAs<Event>(someQuery);
return ret;

Take away the ToJson() call it breaks because BsonClassMap.AutoMap() does not get called which causes BsonClassMap.LookupActualType() to fail. I am not sure how to fix.

Let me know if you need a better description and I can provide one.



 Comments   
Comment by Robert Stam [ 20/Oct/10 ]

Or maybe even:

BsonClassMap.LookupClassMap(typeof(Book));
BsonClassMap.LookupClassMap(typeof(Magazine));

If you're willing to make sure you only call them once you could use:

BsonClassMap.RegisterClassMap<Book>();
BsonClassMap.RegisterClassMap<Magazine>();

RegisterClassMap throws an exception if you try to register the same class more than once.

Or just use the [BsonKnownType] attribute!

Good catch.

Comment by Justin Dearing [ 20/Oct/10 ]

A small amendment to Robert's comment. The correct syntax is:

BsonClassMap.LookupClassMap<Book>();
BsonClassMap.LookupClassMap<Magazine>();

Comment by Robert Stam [ 20/Oct/10 ]

This is the result of an attempt to deserialize an instance of a class that has not yet been mapped (auto or otherwise). The reason calling ToJson first worked is because as a side effect of calling ToJson the class was automapped. This is a common case when you are deserializing the base class of an inheritance hierarchy. The different .NET serializers have various ways of telling the serializer about the "known types" that will be deserialized. In our case, I've added a BsonKnownTypeAttribute for this purpose. Here's a sample family of classes:

[BsonKnownType(typeof(Book))]
[BsonKnownType(typeof(Magazine))]
public class Product {
}

public class Book : Product {
[BsonElement("author")]
public string Author

{ get; set; }

[BsonElement("title")]
public string Title { get; set; }

}

public class Magazine : Product {
[BsonElement("name")]
public string Name

{ get; set; }
}

public class PackingList {
public IList<Product> Products { get; set; }

}

If you don't want to or can't annotate your classes with these attributes another way to make these classes "known" to the serializer is to call:

BsonSerializer.LookupClassMap<Book>();
BsonSerializer.LookupClassMap<Magazine>();

We are ignoring the return values. We only care about the side effect that the class is automapped if necessary (i.e, "known" to the serializer).

Comment by Justin Dearing [ 19/Oct/10 ]

No that was a bad bad search and replace to "sanatize" my code

Foo ret = new Foo();
Trace.TraceInformation("Doing stuff to

{0}

.", ret.ToJson());
ret = collection.FindOneAs<Foo>(someQuery);
return ret;

Comment by Robert Stam [ 19/Oct/10 ]

Is Event supposed to be a subclass of Foo?

Generated at Wed Feb 07 21:35:44 UTC 2024 using Jira 9.7.1#970001-sha1:2222b88b221c4928ef0de3161136cc90c8356a66.