【发布时间】:2021-08-23 15:10:48
【问题描述】:
我尝试序列化和反序列化类许可证。
序列化运行良好,但是当我尝试反序列化文件时 我收到上面的错误消息。
这是基类:
[Serializable]
public abstract class LicenseBase
{
/// <summary>
/// Initializes a new instance of the <see cref="LicenseBase"/> class.
/// </summary>
protected LicenseBase()
{
ApplicationName = string.Empty;
UniqueId = string.Empty;
}
/// <summary>
/// Application name this license is used for
/// </summary>
[Browsable(false)]
public string ApplicationName { get; set; }
/// <summary>
/// Unique hardware id this license will work on
/// </summary>
[Browsable(false)]
public string UniqueId { get; set; }
}
这是派生的:
public class License : LicenseBase
{
[Browsable(false)]
public bool Test { get; set; }
}
这是序列化类的方法:
public void WriteLicense<T>(T license) where T : LicenseBase
{
if (license is null)
{
throw new ArgumentNullException(nameof(license));
}
//Serialize license object into XML
XmlDocument licenseObject = new XmlDocument();
using (StringWriter writer = new StringWriter())
{
XmlSerializer serializer = new XmlSerializer(typeof(LicenseBase), new[]
{
license.GetType(), typeof(License)
});
serializer.Serialize(writer, license);
licenseObject.LoadXml(writer.ToString());
}
//Sign the XML
SignXml(licenseObject);
//Convert the signed XML into BASE64 string
string writeToFile = Convert.ToBase64String(Encoding.UTF8.GetBytes(licenseObject.OuterXml));
File.WriteAllText(LICENSE_FILENAME, writeToFile);
}
这是读取类的代码:
public T ReadLicense<T>() where T : LicenseBase
{
T license;
if (!File.Exists(LICENSE_FILENAME))
{
alarmManager.ReportAlarm(licenseFileMissingAlarm, true, true);
return null;
}
string licenseFileData = File.ReadAllText(LICENSE_FILENAME);
XmlDocument xmlDoc = new XmlDocument { PreserveWhitespace = true };
xmlDoc.LoadXml(Encoding.UTF8.GetString(Convert.FromBase64String(licenseFileData)));
// Verify the signature of the signed XML.
if (VerifyXml(xmlDoc, PrivateKey))
{
XmlNodeList nodeList = xmlDoc.GetElementsByTagName("Signature");
if (xmlDoc.DocumentElement != null)
{
_ = xmlDoc.DocumentElement.RemoveChild(nodeList[0]);
}
string licenseContent = xmlDoc.OuterXml;
//Deserialize license
XmlSerializer serializer = new XmlSerializer(typeof(T));
using (StringReader reader = new StringReader(licenseContent))
{
license = (T)serializer.Deserialize(reader);
}
}
else
{
license = null;
}
return license;
}
licenseContent的内容是
<?xml version="1.0" encoding="UTF-8"?>
<LicenseBase xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="License">
<ApplicationName>Test</ApplicationName>
<UniqueId>c4aed5a8-8d22-47b0-bda4-700ac906bfd5</UniqueId>
<Test>true</Test>
</LicenseBase>
【问题讨论】:
-
我通过验证器 here 运行了您的 XML,并收到消息 “无法将 'License' 解析为元素 'LicenseBase' 的类型定义。”
-
我们可以查看您的许可证类别吗?
-
也许您需要为
XmlSerializer使用不同的构造函数,在其中定义哪个节点是根节点(根据此answer)。请注意,在这里您将使用字符串“LicenseBase”而不是链接答案中的字符串。 -
元素名称是
LicenseBase,并且有一个属性xsi:type="License",这意味着XML是通过使用XML序列化程序new XmlSerializer(typeof(LicenseBase))序列化License类型的对象创建的。您需要在反序列化上做同样的事情,将[XmlInclude(typeof(License))]应用于LicenseBase。为什么请参阅c# xml deserialization to object with colon and hyphen in xsi:type value 和Serialize/Deserialize derived class as base class。 -
事实上这可能是这两个的副本,同意吗?如果没有,您能否请edit 分享您的问题minimal reproducible example,特别是您尝试反序列化的与通用参数
T相对应的实际类型?