我正在使用C#制作Discord机器人,并已准备好所有逻辑,但是,当我尝试从保存配置和其他内容的文件中读取XML时,遇到了问题。
我不想依靠SQLite进行存储。
每当我尝试反序列化时,它都会抛出一个System.InvalidOperationException
和一个System.NullReferenceException
。
IXmlSerializable的自定义实现的示例
namespace RoleBot
{
public class RoleWatch
{
public DiscordGuild Guild { get; set; }
public DiscordChannel Channel { get; set; }
public DiscordMessage Message { get; set; }
public DiscordEmoji Emoji { get; set; }
public DiscordRole Role { get; set; }
public RoleWatch() { }
// Constructor
public RoleWatch(DiscordGuild guild, DiscordChannel channel, string message, DiscordEmoji emoji, DiscordRole role)
{
Guild = guild;
Channel = channel;
Message = Channel.GetMessageAsync(UInt64.Parse(message)).Result;
Emoji = emoji;
Role = role;
}
public RoleWatch(string guild, string channel, string message, string emoji, string role)
{
Guild = Bot.Client.GetGuildAsync(UInt64.Parse(guild)).Result;
Channel = Guild.GetChannel(UInt64.Parse(channel));
Message = Channel.GetMessageAsync(UInt64.Parse(message)).Result;
Emoji = DiscordEmoji.FromName(Bot.Client, emoji);
Role = Guild.GetRole(UInt64.Parse(role));
}
/*
* Custom implementation of the Read method in IXmlSerializable to cater to a descriptive yet consise
* XML config file
*/
public void ReadXml(XmlReader reader)
{
reader.ReadStartElement();
var guild = reader.ReadElementString("Guild");
var channel = reader.ReadElementString("Channel");
var message = reader.ReadElementString("Message");
var emoji = reader.ReadElementString("Emoji");
var role = reader.ReadElementString("RoleID");
reader.ReadEndElement();
Guild = Bot.Client.GetGuildAsync(UInt64.Parse(guild)).Result;
Channel = Guild.GetChannel(UInt64.Parse(channel));
Message = Channel.GetMessageAsync(UInt64.Parse(message)).Result;
Emoji = DiscordEmoji.FromName(Bot.Client, emoji);
Role = Guild.GetRole(UInt64.Parse(role));
}
/*
* Custom implementation of WriteXml method in IXmlSerializable to cater to a descriptive XML file so clients
* can configure without needing to refer to documentation.
*/
public void WriteXml(XmlWriter writer)
{
writer.WriteComment("Guild: " + Guild.Name);
writer.WriteComment("Channel: " + Channel);
writer.WriteComment("Message: " + Message);
writer.WriteComment("Emoji: " + Emoji);
writer.WriteComment("Role: " + Role.Name);
writer.WriteElementString("Guild", Guild.Id.ToString());
writer.WriteElementString("Channel", Channel.Id.ToString());
writer.WriteElementString("Message", Message.Id.ToString());
writer.WriteElementString("Emoji", Emoji.GetDiscordName());
writer.WriteElementString("RoleID", Role.Id.ToString());
}
}
}
这是要反序列化和序列化的XML文件
<?xml version="1.0" encoding="utf-8"?>
<Config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<AutoRemoveFlag>false</AutoRemoveFlag>
<Prefix>r!</Prefix>
<Role>
<!--Guild: The Failures-->
<!--Channel: Channel #test (485962904466751494)-->
<!--Message: Message 496344956252717056; Attachment count: 0; Embed count: 0; Contents: Add Reaction Here-->
<!--Emoji: <:nut:473756909610991626>-->
<!--Role: nut-->
<Guild>397456625813815297</Guild>
<Channel>485962904466751494</Channel>
<Message>496344956252717056</Message>
<Emoji>:nut:</Emoji>
<RoleID>505000750632534017</RoleID>
</Role>
<Role>
<!--Guild: The Failures-->
<!--Channel: Channel #test (485962904466751494)-->
<!--Message: Message 496344956252717056; Attachment count: 0; Embed count: 0; Contents: Add Reaction Here-->
<!--Emoji: <:confusedCopy:473756234735026176>-->
<!--Role: memes-->
<Guild>397456625813815297</Guild>
<Channel>485962904466751494</Channel>
<Message>496344956252717056</Message>
<Emoji>:confusedCopy:</Emoji>
<RoleID>505000818647367680</RoleID>
</Role>
</Config>
每个RoleWatch
对象都存储在以下类的List
中
namespace RoleBot
{
[XmlInclude(typeof(List<RoleWatch>))]
public class Config
{
public string Token { get; set; }
public bool AutoRemoveFlag { get; set; }
[XmlElement("Prefix")]
public string CommandPrefix { get; set; }
[XmlElement("Role")]
public List<RoleWatch> RolesToWatch { get; set; }
public Config () { RolesToWatch = new List<RoleWatch>(); }
}
}
这些是调用序列化器和反序列化器的方法:
/* Refresh Config Method
*
* Used to load the configuration into the assembly
* Gets each <Role> Node from config.xml and deserializes them into RoleWatch Objects
*/
internal static Task RefreshConfig ()
{
using (var reader = new StreamReader(ConfigPath))
{
var serializer = new XmlSerializer(typeof(Config));
Config = serializer.Deserialize(reader) as Config;
}
return Task.CompletedTask;
}
/*
* Updates the config file for permanent storage of settings and roles to watch
*/
internal static Task UpdateConfigFile()
{
using (var writer = XmlWriter.Create("config.xml", new XmlWriterSettings {Indent = true}))
{
/*
* Initializes a new XmlSerializer with type config and RoleWatch
*/
var serializer = new XmlSerializer(typeof(Config));
serializer.Serialize(writer, Config);
}
return Task.CompletedTask;
}
我尝试了在堆栈溢出中发现的所有可能方法,但似乎没有任何效果! 任何帮助将不胜感激! 谢谢。