gpt4 book ai didi

c# - 具有从非泛型基类继承的泛型类的 MongoDB C# 驱动程序类型鉴别器

转载 作者:IT老高 更新时间:2023-10-28 13:25:13 34 4
gpt4 key购买 nike

我正在尝试使用官方 C# 驱动程序存储从 mongodb 中的非泛型基类继承的泛型类的对象列表。

我的代码如下所示:

abstract class MyAbstractClass {}

class MyGenericClass<T>: MyAbstractClass
{
[BsonRequired]
public List<T> Values = new List<T>();

public MyGenericClass(IEnumerable<T> values)
{
Values.AddRange(values);
}
}

class MyContainerClass
{
[BsonId]
public string Id;

[BsonRequired]
public List<MyAbstractClass> ValueCollections = new List<MyAbstractClass>();

public MyContainerClass()
{
Id = Guid.NewGuid().ToString();
}
}

在测试时,我创建一个容器对象并用泛型类的实例填充它,如下所示:

var container = new MyContainerClass();
container.ValueCollections.Add(new MyGenericClass<string>(new[]{"foo","bar","baz"}));

当我将它保存到数据库时,添加的文档如下所示:

{
"_id": "c5cf5cd1-843f-4d5d-ba8f-5859ae62fd1d",
"ValueCollections": [
{
"_t": "MyGenericClass`1",
"Values": [
"foo",
"bar",
"baz"
]
}
]
}

类型鉴别器获取类型“MyGenericClass'1”而不是“MyGenericClass'1[System.String]”,这意味着它不可能再次反序列化。

此外,当尝试从数据库加载这些对象时,我收到一条错误消息:无法创建抽象类的实例。但是类型鉴别器(如果它是正确的)应该允许驱动程序看到它不应该创建 MyAbstractClass 类型的对象,而是 MyGenericClass

所以我的问题是:1. 为什么会出现这个错误?2. 为什么没有正确序列化判别器?

感谢您的宝贵时间。

最佳答案

经过一些实验,我发现您可以编写自己的鉴别器约定。我真的不明白为什么,但默认的鉴别器约定似乎使用类型类的 Name 属性,而不是 FullName,这使得它对泛型类毫无用处。

我最终改用了这段代码:

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;
}
}

并用

注册它
BsonSerializer.RegisterDiscriminatorConvention(typeof(MyGenericClass<>), new FooDiscriminatorConvention()); //is this needed?
BsonSerializer.RegisterDiscriminatorConvention(typeof(MyAbstractClass), new FooDiscriminatorConvention());

我还必须使基类成为非抽象类,以避免“无法创建抽象类的实例”错误。能够拥有一个抽象基类会很好,但由于派生类是泛型的,我不能使用 BsonKnownTypes。

关于c# - 具有从非泛型基类继承的泛型类的 MongoDB C# 驱动程序类型鉴别器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25891373/

34 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com