首先,澄清一下:
据我了解,如果一个类没有构造函数,则始终会创建默认构造函数,这让我有些难以理解,如果将默认构造函数指定为私有,那么是否可以呢?
这不是真的。当定义一个没有构造函数的类时,会自动生成一个默认的无参构造函数。如果您提供了构造函数,则不再生成此默认构造函数。换句话说,一个类可能没有默认构造函数。
考虑到这一点,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
。然后,我们从该JObject
中挑选出HeaderId
和Value
,以创建一个Header
实例。
需要注意的是:我不太了解这个库。这可能不是初始化Header
的最佳方式,而且我可能会意外地丢弃一些信息。我只进行了一些非常基本的测试。
一旦您解决了这个问题,您就会遇到另一个与属性设置器有关的问题,这些属性设置器不接受null
值。
具体来说,ResentMessageId
和MimeVersion
属性在设置器中具有逻辑,如果您提供null
,则会抛出ArgumentException
。这是一个问题,因为当实例化MimeMessage
时,这些值可以为null。
解决这个问题的一个方法是创建一个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()
}
});
通过一些基本测试,似乎这个工作得很好。但在实际使用中可能会出现更多问题,所以无法保证。
希望这至少能让你开始。