Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/154.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 使用JSON.NET自定义异常覆盖消息_C#_Asp.net_Json_Serialization_Json.net - Fatal编程技术网

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);
    }
}
这两种解决方案都避免了代码气味