首先,要澄清一些事情:
我的理解是总是创建一个默认构造函数,这让我有点难以理解,默认构造函数是否已被指定为私有,如果是,为什么?
这不是真的。当您定义一个没有构造函数的类时,会为您生成一个默认的、无参数的构造函数。如果您提供构造函数,则不再生成此默认构造函数。换句话说,一个类可能没有默认构造函数。
考虑到这一点,MimeKit.Header
该类提供了 6 个构造函数,其中没有一个不带参数。正因为如此,JSON.NET 不知道如何实例化这个类,这就是发生异常的原因。
由于您对类没有任何控制权,因此MimeKit.Header
让 JSON.NET 知道如何构造Header
实例的一种方法是使用自定义转换器:
public class MimeHeaderConverter : JsonConverter
{
public override object ReadJson(
JsonReader reader,
Type objectType,
object existingValue,
JsonSerializer serializer)
{
JObject obj = serializer.Deserialize<JObject>(reader);
HeaderId headerId = obj["Id"].ToObject<HeaderId>();
Header header = new Header(headerId, obj["Value"].ToObject<string>());
return header;
}
public override void WriteJson(
JsonWriter writer,
object value,
JsonSerializer serializer)
{
throw new NotImplementedException();
}
public override bool CanConvert(Type t)
{
return typeof(Header).IsAssignableFrom(t);
}
public override bool CanRead { get { return true; } }
public override bool CanWrite { get { return false; } }
}
在这里,我们将这个Header
类反序列化为JObject
第一个。然后,我们从中挑选HeaderId
出来Value
以JObject
创建一个Header
实例。
这里要注意:我对这个库了解不多。这可能不是实例化 a 的最佳方式Header
,而且我可能会不小心丢弃一些信息。我只做了一些非常基本的测试。
一旦你解决了这个问题,你就会遇到另一个与不接受null
值的属性设置器有关的问题。
具体来说,ResentMessageId
andMimeVersion
属性在 setter 中有逻辑,ArgumentException
如果你提供 s 就会抛出 s null
。这是一个问题,因为在实例化时这些值可能为空。MimeMessage
一种解决方法是创建一个ContractResolver
排除这些属性的方法:
public class MimeMessageContractResolver : DefaultContractResolver
{
private static HashSet<string> excludedMembers = new HashSet<string>
{
"ResentMessageId",
"MimeVersion"
};
protected override List<MemberInfo> GetSerializableMembers(Type objectType)
{
var baseMembers = base.GetSerializableMembers(objectType);
if (typeof(MimeMessage).IsAssignableFrom(objectType))
{
baseMembers.RemoveAll(m => excludedMembers.Contains(m.Name));
}
return baseMembers;
}
}
这样,我们就不会意外地将null
这些属性之一传递给 setter。
这里还有一个注意事项:我注意到即使我忽略了MimeVersion
,ResentMessageId
如果标题包含一个MimeVersion
和/或ResentMessageId
标题,它们仍然会被设置。我猜这是在MimeMessage
某处被烤熟的,但同样,我对这个库并不完全熟悉。
因此,要使用上面的类(仅在反序列化时),您可以这样做:
string someJsonString = "{ ... }";
MimeMessage deserialized = JsonConvert.DeserializeObject<MimeMessage>(
someJsonString, new JsonSerializerSettings
{
ContractResolver = new MimeMessageContractResolver(),
Converters = new JsonConverter[]
{
new MimeHeaderConverter()
}
});
通过一些基本测试,这似乎工作正常。您在实际使用中可能会遇到更多问题,因此无法保证。
希望这至少能让你开始。