2016-10-20 10 views
2

DateTimeをデシリアライズした後、中央の場所でいくつかのものをやりたいだから私は契約にコールバックをフックすると思ったが、彼らは決して呼び出されません。 アイデアNewtonSoft JsonContract OnDeserializedCallbacksはプリミティブ型に対して呼び出されませんか?

public class MyContractResolver : DefaultContractResolver 
    { 
     protected override JsonContract CreateContract(Type objectType) 
     { 
      var result = base.CreateContract(objectType); 
      var primContract = result as JsonPrimitiveContract; 
      if (primContract != null && primContract.CreatedType == typeof(DateTime)) 
      { 
       primContract.OnDeserializingCallbacks.Add((o, context) => 
       { 
        var test = o; 
       }); 
       primContract.OnDeserializedCallbacks.Add((o, context) => 
       { 
        var test = o; 
       }); 
      } 
      return result; 
     } 
    } 

コールバックは追加されますが、コールされることはありません。

答えて

0

あなたはそうです - これを再現できました(デモfiddle)。

TypeConverter

JsonStringContractによって処理されるように(例えばSystem.Drawing.Colorとして)がインストールされ、持って非プリミティブ型のため、あっても他人は、OnSerializingOnSerializedコールバックが呼び出され、なく、対応するデシリアライゼーションコールバックされます。

report an issueです。値の意味を持っているなどDateTimeようなタイプのために、それは行わない、ということ

public class MyContractResolver : DefaultContractResolver 
{ 
    protected override JsonContract CreateContract(Type objectType) 
    { 
     var result = base.CreateContract(objectType); 
     var primContract = result as JsonPrimitiveContract; 
     if (primContract != null 
      && (primContract.CreatedType == typeof(DateTime) || primContract.CreatedType == typeof(DateTime?)) 
      && primContract.Converter == null 
      ) 
     { 
      //Console.WriteLine("Adding {0} callbacks for {1}", primContract.ToString(), objectType.ToString()); 
      var converter = new MyIsoDateTimeConverter(); 
      converter.OnDeserializingCallbacks.Add((o, context) => 
      { 
       Console.WriteLine("Deserializing " + o); 
      }); 
      converter.OnDeserializedCallbacks.Add((o, context) => 
      { 
       Console.WriteLine("Deserialized " + o); 
      }); 
      primContract.Converter = converter; 
     } 
     return result; 
    } 
} 

class MyIsoDateTimeConverter : Newtonsoft.Json.Converters.IsoDateTimeConverter 
{ 
    private List<SerializationCallback> _onDeserializingCallbacks; 
    private List<SerializationCallback> _onDeserializedCallbacks; 

    public IList<SerializationCallback> OnDeserializingCallbacks 
    { 
     get 
     { 
      if (_onDeserializingCallbacks == null) 
      { 
       Interlocked.CompareExchange(ref _onDeserializingCallbacks, new List<SerializationCallback>(), null); 
      } 
      return _onDeserializingCallbacks; 
     } 
    } 

    public IList<SerializationCallback> OnDeserializedCallbacks 
    { 
     get 
     { 
      if (_onDeserializedCallbacks == null) 
      { 
       Interlocked.CompareExchange(ref _onDeserializedCallbacks, new List<SerializationCallback>(), null); 
      } 
      return _onDeserializedCallbacks; 
     } 
    } 

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) 
    { 
     var value = base.ReadJson(reader, objectType, existingValue, serializer); 
     if (value != null && value is DateTime) 
     { 
      if (_onDeserializingCallbacks != null) 
      { 
       foreach (var callback in _onDeserializingCallbacks) 
        callback(value, serializer.Context); 
      } 
      if (_onDeserializedCallbacks != null) 
      { 
       foreach (var callback in _onDeserializedCallbacks) 
        callback(value, serializer.Context); 
      } 
     } 

     return value; 
    } 
} 

注:なお

、あなたはIsoDateTimeConverterまたはDateTimeConverterBaseから継承他のいくつかのコンバータをサブクラス化でき、そこにコールバックを追加しますオブジェクトが構築された後、オブジェクトが作成される前にOnDeserializingイベントを呼び出すことは、オブジェクトが構築時に完全に埋め込まれているためです。したがって、デシリアライズ後に両方のイベントを呼び出しました。

また、IsoDateTimeConverterがあなたのニーズを満たしていることを確認するためにSerializing Dates in JSONを読んでください。

fiddle

+0

私が達成したいのはこれです:残りのAPIからUTCのdatetimes(Kind = UTC)を受け取りました。私はこれらを私のWebアプリケーションのユーザごとに設定されたタイムゾーンを使って、ローカルのdatetimeに変換します。私は中央の場所でそれをしたい。しかし、あなたが指摘したように、デシリアライズ時にこれを行うことはできません。datetimeはすでに構築されており、新しいインスタンスを返すことができないからです。だから、私はデフォルトのdatetime文字列セマンティクスでうまくいますが、コンバータを作成する必要があると思います。 –

+0

@JaapMosselman - 独自の 'DateTime'コンバーターを作成し、' ReadJson() 'の最後に変更を加えることは、その時に行く方法のようです。スタックオーバーフローに関する質問の推奨形式は、[投稿ごとに1つの質問](https://meta.stackexchange.com/questions/222735/can- 1件につき1つの質問のみ)。 – dbc

関連する問題