C# 使用JSON.NET自定义异常覆盖消息
如果您创建了一个自定义异常,该异常使用以下内容覆盖虚拟财产C# 使用JSON.NET自定义异常覆盖消息,c#,asp.net,json,serialization,json.net,C#,Asp.net,Json,Serialization,Json.net,如果您创建了一个自定义异常,该异常使用以下内容覆盖虚拟财产消息: public class GrossException : Exception { public GrossException() : base("Eww, gross") { } } public class BarfException : GrossException { public override string Message { get; } = "BARF!!"; } 然后,当通过ASP.NET使
消息
:
public class GrossException : Exception
{
public GrossException() : base("Eww, gross") { }
}
public class BarfException : GrossException
{
public override string Message { get; } = "BARF!!";
}
然后,当通过ASP.NET使用JSON.NET发送BarfeException
时,消息
属性将包含
“嗯,总的”
而不是重写的值。我相信这与异常实现了ISerializable
这一事实有关,但是既然消息
属性是虚拟的,我是否应该被允许这样重写它并使它仍然工作
是否有适当的方法来实现异常,并能够覆盖
消息
属性并使其仍能工作?发生这种情况是正确的,因为异常
实现了Json.NET。具体来说,从引用源,在方法中,异常
类型序列化基础字段,而不是属性:
info.AddValue("Message", _message, typeof(String));
Microsoft之所以这样做,可能是因为如果未设置基础字段,则消息
属性具有默认值:
public virtual String Message {
get {
if (_message == null) {
if (_className==null) {
_className = GetClassName();
}
return Environment.GetResourceString("Exception_WasThrown", _className);
} else {
return _message;
}
}
}
通过序列化字段而不是属性,具有默认消息的异常将在反序列化时在接收系统的CurrentUICulture
中自动显示其可见消息
因此,如果希望消息属性的值显示在JSON中,而不是底层字段中,则需要重写。而且,如果您尝试添加与预先存在的值同名的值,并且没有替换当前值的SetValue()
方法,则会引发异常,因此您需要执行一些带有代码味道的操作:
public class GrossException : Exception
{
public GrossException() : base("Eww, gross") { }
protected GrossException(SerializationInfo info, StreamingContext context) : base(info, context) { }
}
public class BarfException : GrossException
{
public BarfException() : base() { }
protected BarfException(SerializationInfo info, StreamingContext context) : base(info, context) { }
public override string Message { get { return "BARF!!"; } }
public override void GetObjectData(SerializationInfo info, StreamingContext context)
{
var tempInfo = new SerializationInfo(GetType(), new FormatterConverter());
base.GetObjectData(tempInfo, context);
foreach (SerializationEntry entry in tempInfo)
{
if (entry.Name != "Message")
{
info.AddValue(entry.Name, entry.Value, entry.ObjectType);
}
}
info.AddValue("Message", Message);
}
}
如您所见,此解决方案违反了继承层次结构的设计,因为基础\u消息
字段的值不再是基类GrossException
所需的值。但至少JSON很漂亮
更好的解决方案是修改GrossException
类型,使其具有可指定消息的受保护构造函数:
public class GrossException : Exception
{
public GrossException() : base("Eww, gross") { }
protected GrossException(SerializationInfo info, StreamingContext context) : base(info, context) { }
protected GrossException(string message) : base(message) { }
}
或者,如果您只是想在JSON中查看被重写的消息以进行调试(比如,因为您正在记录异常),您可以将其添加到序列化流中,如下所示:
public class BarfException : GrossException
{
public BarfException() : base() { }
protected BarfException(SerializationInfo info, StreamingContext context) : base(info, context) { }
public override string Message { get { return "BARF!!"; } }
public override void GetObjectData(SerializationInfo info, StreamingContext context)
{
base.GetObjectData(info, context);
info.AddValue("OverriddenMessage", Message);
}
}
这两种解决方案都避免了代码气味