gpt4 book ai didi

c# - 使用 JSON.NET 的自定义异常覆盖消息

转载 作者:行者123 更新时间:2023-11-30 20:33:40 25 4
gpt4 key购买 nike

如果您创建一个自定义异常来覆盖虚拟属性 Message,如下所示:

public class GrossException : Exception
{
public GrossException() : base("Eww, gross") { }
}

public class BarfException : GrossException
{
public override string Message { get; } = "BARF!!";
}

然后,当通过 ASP.NET 使用 JSON.NET 发送 BarfException 时,Message 属性将包含

"Eww, gross"

而不是覆盖值。我相信这与 Exception 实现 ISerializable 的事实有关,但是由于 Message 属性是虚拟的,我是否应该不允许像这样重写它并让它继续工作?

是否有适当的方法来实现异常并能够覆盖 Message 属性并仍然让它工作?

最佳答案

你是对的,这是因为 Exception 实现了 ISerializable和 Json.NET supports this interface .具体来说,从引用源,在方法Exception.GetObjectData(SerializationInfo info, StreamingContext context)Exception 类型序列化底层的字段,而不是属性:

        info.AddValue("Message", _message, typeof(String));

Microsoft 可能已经这样做了,因为如果未设置基础字段,Message 属性具有默认值:

    public virtual String Message {
get {
if (_message == null) {
if (_className==null) {
_className = GetClassName();
}
return Environment.GetResourceString("Exception_WasThrown", _className);

} else {
return _message;
}
}
}

通过序列化字段而不是属性,默认消息的异常将在反序列化时自动显示在接收系统的 CurrentUICulture 中。

因此,如果您希望消息属性的值出现在 JSON 中,而不是基础字段中,您将需要覆盖 GetObjectData() .而且,自 AddValue()如果您尝试添加一个与预先存在的值同名的值,则抛出异常,并且 SerializationInfo没有 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);
}
}

如您所见,此解决方案违反了继承层次结构的设计,因为底层 _message 字段的值不再是基类需要的值 严重异常。但至少 JSON 很漂亮。

更好的解决方案是修改 GrossException 类型,使其具有一个 protected 构造函数,可以在其中指定消息:

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);
}
}

这两种解决方案都避免了代码异味。

关于c# - 使用 JSON.NET 的自定义异常覆盖消息,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39984110/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com