Sau một số thử nghiệm, tôi phát hiện ra rằng bạn có thể viết các quy ước phân biệt đối xử của riêng bạn. Tôi thực sự không thể hiểu tại sao, nhưng quy ước phân biệt đối xử mặc định dường như sử dụng thuộc tính Tên của lớp kiểu, thay vì Tên đầy đủ, điều này làm cho nó trở nên vô dụng đối với các lớp chung.
Tôi đã kết thúc bằng cách sử dụng mã này thay thế:
class FooDiscriminatorConvention : IDiscriminatorConvention
{
public string ElementName
{
get { return "_t"; }
}
public Type GetActualType(MongoDB.Bson.IO.BsonReader bsonReader, Type nominalType)
{
if(nominalType!=typeof(MyAbstractClass))
throw new Exception("Cannot use FooDiscriminator for type " + nominalType);
var ret = nominalType;
var bookmark = bsonReader.GetBookmark();
bsonReader.ReadStartDocument();
if (bsonReader.FindElement(ElementName))
{
var value = bsonReader.ReadString();
ret = Type.GetType(value);
if(ret==null)
throw new Exception("Could not find type " + value);
if(!ret.IsSubclassOf(typeof(MyAbstractClass)))
throw new Exception("Database type does not inherit from MyAbstractClass.");
}
bsonReader.ReturnToBookmark(bookmark);
return ret;
}
public BsonValue GetDiscriminator(Type nominalType, Type actualType)
{
if (nominalType != typeof(MyAbstractClass))
throw new Exception("Cannot use FooDiscriminator for type " + nominalType);
return actualType.FullName;
}
}
Và đăng ký với
BsonSerializer.RegisterDiscriminatorConvention(typeof(MyGenericClass<>), new FooDiscriminatorConvention()); //is this needed?
BsonSerializer.RegisterDiscriminatorConvention(typeof(MyAbstractClass), new FooDiscriminatorConvention());
Tôi cũng phải làm cho lớp cơ sở không trừu tượng, để tránh lỗi "không thể tạo các trường hợp trừu tượng của lớp trừu tượng". Sẽ rất tuyệt nếu có thể có một lớp cơ sở trừu tượng, nhưng vì lớp dẫn xuất là chung nên tôi không thể sử dụng BsonKnownTypes.