在尝试对某些代码进行故障排除时,我查看了我捕获任何未处理异常的日志。
在我的日志功能中,我有以下代码行:
data = JsonConvert.DeserializeObject(exception)
数据的部分值读取," Message \":null。当我调试并查看异常时,异常的Message属性有一个值(准确描述了问题)。如果我尝试使用上面的行将不同的异常转换为JSON,我会在生成的JSON中看到Message属性的值。
我错过了什么?
答案 0 :(得分:3)
这看起来像AutoMapperMappingException
中的错误。 Json.NET支持ISerializable
,基类System.Exception
实现此接口。从reference source可以看出,GetObjectData
的基类版本只是将基本字段值而不是属性值添加到序列化流中:
info.AddValue("Message", _message, typeof(String));
Exception
的任何子类,包含基类之上和之外的其他数据,必须覆盖GetObjectData
并序列化自己的数据。例如,这是ArgumentOutOfRangeException
的实现:
public override void GetObjectData(SerializationInfo info, StreamingContext context) {
if (info==null) {
throw new ArgumentNullException("info");
}
Contract.EndContractBlock();
base.GetObjectData(info, context);
info.AddValue("ActualValue", m_actualValue, typeof(Object));
}
现在,从其source code,AutoMapperMappingException
覆盖Exception.Message
来输出其他数据。实际上,基本消息可能为null:
public override string Message
{
get
{
string message = null;
var newLine = Environment.NewLine;
if (Context != null)
{
message = _message + newLine + newLine + "Mapping types:";
message += newLine + string.Format("{0} -> {1}", Context.SourceType.Name, Context.DestinationType.Name);
message += newLine + string.Format("{0} -> {1}", Context.SourceType.FullName, Context.DestinationType.FullName);
var destPath = GetDestPath(Context);
message += newLine + newLine + "Destination path:" + newLine + destPath;
message += newLine + newLine + "Source value:" + newLine + (Context.SourceValue ?? "(null)");
return message;
}
if (_message != null)
{
message = _message;
}
message = (message == null ? null : message + newLine) + base.Message;
return message;
}
}
不,但是,覆盖GetObjectData()
,这就是错误。
要解决此问题,您可以编写自己的自定义JsonConverter
并序列化邮件属性而不是基本字段:
public class ExceptionConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return typeof(AutoMapperMappingException).IsAssignableFrom(objectType);
}
public override bool CanRead { get { return false; } }
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
throw new NotImplementedException();
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
var exception = (Exception)value;
var obj = JObject.FromObject(exception);
obj["Message"] = exception.Message;
obj.WriteTo(writer);
}
}
这至少可以确保消息存在。但是,ResolutionContext
的AutoMapperMappingException
属性仍然不会被序列化,因此生成的反序列化异常将丢失一些数据。
或者,您可以尝试使用Json.NET的默认序列化对ResolutionContext
进行序列化和反序列化,并将其作为转换器中的属性添加。不确定它是否会起作用,但它可能会起作用。或者尝试report an issue。
(或者,只需记录异常的ToString()
输出,这通常就足够了。)