I am developing a project that uses MongoDB (with C# driver) and DDD.
I have a class (aggregate) which have a property whi
[BsonSerializer(typeof(ImpliedImplementationInterfaceSerializer<IReviewExpert, ReviewExpert>))]
public IReviewExpert Expert { get; set; }
works for me
We are on the 1.x branch of mongo drivers and that sadly doesn't have the ImpliedImplementationInterfaceSerializer
that was suggested by Robert Baker which seems to be otherwise a good solution. To this end I created my own serializer that allows you to specify a confcrete type for an interface member.
public class ConcreteTypeSerializer<TInterface, TImplementation> : BsonBaseSerializer where TImplementation : TInterface
{
private readonly Lazy<IBsonSerializer> _lazyImplementationSerializer;
public ConcreteTypeSerializer()
{
var serializer = BsonSerializer.LookupSerializer(typeof(TImplementation));
_lazyImplementationSerializer = new Lazy<IBsonSerializer>(() => serializer);
}
public override object Deserialize(BsonReader bsonReader, Type nominalType, Type actualType, IBsonSerializationOptions options)
{
if (bsonReader.GetCurrentBsonType() == BsonType.Null)
{
bsonReader.ReadNull();
return default(TInterface);
}
else
{
return _lazyImplementationSerializer.Value.Deserialize(bsonReader, nominalType, typeof(TImplementation), options);
}
}
public override void Serialize(BsonWriter bsonWriter, Type nominalType, object value, IBsonSerializationOptions options)
{
if (value == null)
{
bsonWriter.WriteNull();
}
else
{
var actualType = value.GetType();
if (actualType == typeof(TImplementation))
{
_lazyImplementationSerializer.Value.Serialize(bsonWriter, nominalType, (TImplementation)value, options);
}
else
{
var serializer = BsonSerializer.LookupSerializer(actualType);
serializer.Serialize(bsonWriter, nominalType, value, options);
}
}
}
}
Usage is as follows:
[BsonSerializer(typeof(ConcreteTypeSerializer<IMyInterface,MyClass>))]
public IMyInterface MyProperty {get; set;}
A few notes on the code - all it really does is lazily loads the serializer for the appropriate concrete type and then passes on all the serialize/deserialize calls to that with the appropriate concrete type instead of the interface.
It also checks that the type is actually of the expected type and if not just finds the default serializer for the type.
Well, I have found a lot of problems when trying to get this answer.
First of all, the MongoDB C# Driver, does have some problems when deserializing interfaces, like said by Craig Wilson in this question comments, and as described in the issue page.
The secure implementation for this problem, like I said before, really may be a custom BSON serializer or a specific class map, using BsonClassMap.RegisterClassMap
.
So, I have implemented the class map and the problem persisted.
Looking forward with the problem, I have found that exception is related to another issue of the driver: the problem when deserializing structs
.
I have rolled back the project to the initial state (without classes map or custom serializers) and changed the struct type to class type, and it worked.
In resume, this exception error is related to structs deserialization, not with interfaces deserialization.
Anyway, it is a real problem, and the second issue needs to be considered more a bug than a improvement, like the first issue is.
You can find the issues at these links: