2016-10-11 9 views
2

によるカスタム例外オーバーライド・メッセージあなたがこのような何かを持つ仮想プロパティMessageをオーバーライドするカスタム例外を作成する場合:JSON.NET

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プロパティは、代わりにオーバーライドされVALUの "総EWW、"

が含まれていますe。これは例外がISerializableを実装しているという事実に関連していると思いますが、プロパティは仮想であるため、このようにオーバーライドすることはできないのですか?

Exceptionを実装し、プロパティをオーバーライドしても問題なく動作する適切な方法はありますか?

答えて

3

ExceptionISerializableとJson.NET supports this interfaceを実装しているため、これが起こっていることは間違いありません。

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

Messageプロパティが基になるフィールド場合は、デフォルト値を持っているため、Microsoftはこれを行っていることがあります。具体的には、参照元から、方法Exception.GetObjectData(SerializationInfo info, StreamingContext context)で、Exceptionタイプは、基礎となるフィールド、ないプロパティをシリアライズ設定されていない。

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フィールドの値は、もはや、基本クラスGrossExceptionによってを必要な値であることから、このソリューションは、あなたの継承階層の設計に違反していません。しかし、少なくともJSONはかなりです。

より良い解決策は、メッセージを指定することができるprotectedコンストラクタ持って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); 
    } 
} 

どちらのソリューションは、コードのにおいを回避することができます。