如何解决除非我先写入数据库,否则无法创建抽象类的实例
当我第一次尝试使用读取功能时,我遇到了两个错误,其中一个用于写入,一个用于读取:
这是我没有得到的,如果我至少先使用一次写入,则读取工作正常。我不明白在后台发生了什么,如果我们使用它编写一次,就可以初始化抽象类。
if (BsonClassMap.IsClassMapRegistered(typeof(MessageContainer)))
{
BsonClassMap.RegisterClassMap<MessageBase>(cm =>
{
cm.AutoMap();
cm.SetIsRootClass(true);
});
}
这是我用于mongo集合的课程。
[BsonIgnoreExtraElements(true)]
public class MessageContainer
{
[BsonId]
public ObjectId Id { get; set; }
[BsonDateTimeOptions(Kind = DateTimeKind.Utc)]
public DateTime TimeStamp { get; set; }
[BsonElement]
public string MessageType { get; set; }
public MessageBase Message { get; set; }
[BsonConstructor]
public MessageContainer()
{
}
[BsonConstructor]
public MessageContainer(MessageBase message)
{
Message = message ?? throw new ArgumentNullException(nameof(message));
TimeStamp = DateTime.UtcNow;
MessageType = message.GetType().Name;
}
[BsonConstructor]
public MessageContainer(DateTime timeStamp,string messageType,MessageBase message)
{
TimeStamp = timeStamp;
MessageType = messageType ?? throw new ArgumentNullException(nameof(messageType));
Message = message ?? throw new ArgumentNullException(nameof(message));
}
}
里面的抽象类:
public abstract class MessageBase
{
protected MessageBase();
public MessageBase Createcopy();
}
写入方法示例:
public bool Write(MessageContainer message)
{
if (message != null && _mongoCollection != null)
{
try
{
if (!BsonClassMap.IsClassMapRegistered(typeof(MessageContainer)))
{
BsonClassMap.RegisterClassMap<MessageContainer>();
BsonClassMap.RegisterClassMap<MessageBase>(cm =>
{
cm.AutoMap();
cm.SetIsRootClass(true);
});
}
_mongoCollection.InsertOne(message);
return true;
}
catch (Exception Ex)
{
Console.WriteLine(Ex.Message);
}
}
return false;
}
读取方法示例:
public bool GetFirstAndLastMessageTime(out DateTime firstMessageTime,out DateTime lastMessageTime)
{
if (BsonClassMap.IsClassMapRegistered(typeof(MessageContainer)))
{
BsonClassMap.RegisterClassMap<MessageBase>(cm =>
{
cm.AutoMap();
cm.SetIsRootClass(true);
});
}
var filter = Builders<MessageContainer>.Filter.Empty;
var first = _mongoCollection.Find(filter).sort(Builders<MessageContainer>.sort.Ascending("TimeStamp")).Limit(5).ToList().First();
var last = _mongoCollection.Find(filter).sort(Builders<MessageContainer>.sort.Descending("TimeStamp")).Limit(5).ToList().First();
firstMessageTime = first.TimeStamp;
lastMessageTime = last.TimeStamp;
return true;
}
我缺少什么才能能够初始化抽象类而无需先编写?
解决方法
好吧,这里是一种反模式(我不喜欢将基类的依赖项添加到其实现中),但是快速解决方案是添加
[BsonKnownTypes(typeof(MyImplementation))]
其中MyImplementation
是实现抽象类的类型。
MessageBase
班上。对我来说,这样做很成功-我能够读取数据并进行反序列化。我也不必添加任何类映射。
,尽管提供的阿米特拉答案是正确的,但由于多种原因,它对我而言并不起作用。
一个是我不想更改抽象类并将所有实现记为标签。
另一个要点是,我在MongoDB论坛上发现,显然只有写后才起作用的原因是自动映射器,这就是为什么写后才对我起作用的原因。
所以要做的就是我所做的:
public void RegisterClassMapping(List<string> messagesType)
{
// Map base class first
BsonClassMap.RegisterClassMap<MessageBase>(cm =>
{
cm.AutoMap();
cm.SetIsRootClass(true);
});
if (messagesType.Count > 0)
{
foreach (string message in messagesType) // Do look up for each message
{
Type type = GetType("NAMEOFTHENAMESPACE." + message);
if (type == null)
{
type = GetType("NAMEOFTHENAMESPACE." + message);
}
if (type != null && !BsonClassMap.IsClassMapRegistered(type))
{
BsonClassMap.LookupClassMap(type);
}
}
}
}
这是我使用的通用GetType:
private Type GetType(string typeName)
{
var type = Type.GetType(typeName);
if (type != null) return type;
foreach (var a in AppDomain.CurrentDomain.GetAssemblies())
{
type = a.GetType(typeName);
if (type != null)
return type;
}
return null;
}
我只运行了一次,剩下的时间就可以使用了。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。