web-dev-qa-db-ja.com

JSON.NETは、Typeパラメーターを使用してオブジェクトにデシリアライズします

次の問題があり、解決できません。

IProtocolという名前のインターフェイスをすべて実装するさまざまなクラスがあります。現時点では、SimpleProtocolParallelProtocolと名付けられています。これらのオブジェクトを永続化したかったため、JSON.NETを使用しましたが、すべて正常に動作します。私がそれらをデシリアライズしようとしている場合を除いて、それが想定されているタイプを知っているとき、それは完璧に動作します、例えば:

SimpleProtocol p = JsonConvert.DeserializeObject<SimpleProtocol>(myJsonData);

しかし、私は現在、JSONデータをロードしてIProtocolを取得したい状況にありますが、それは当然、JSONによって許可されていません。たとえば、このようなことはnot動作します:

IProtocol p1 = JsonConvert.DeserializeObject<IProtocol>(myJsonData); // does not work
IProtocol p2 = (IProtocol)JsonConvert.DeserializeObject(myJsonData); // also, does not work

[〜#〜] api [〜#〜] を検索すると、このメソッドシグネチャが見つかりました。

public static Object DeserializeObject(
    string value,
    Type type
)

これは私が必要とするもののように見えるので、文字列の型を永続化して取得することで試してください:

// test
Type protocolType = Type.GetType("MyApp.Protocols.SimpleProtocol");
IProtocol p1 = JsonConvert.DeserializeObject(myJsonData, protocolType);

Newtonsoft.Json.Linq.JObjectIProtocolにキャストできないというエラーが表示されます。これは奇妙で、これを解決する方法がわかりません。

Typeオブジェクトをジェネリックメソッドで渡すことは不可能なので、基本的にここで立ち往生しています。できればReflectionを使用せずに、これを解決する方法はありますか?これは完全に通常のユースケースであるように思えます。

私にできることは、少し「汚い」ように思えますが、IProtocolインスタンスを保持する単純なラッパークラスを作成し、それをシリアライズ/デシリアライズすることですか?

22
avanwieringen

結局のところ、この方法を使用することによる私の最初のアプローチは正しいように思えました。

_public static Object DeserializeObject(
    string value,
    Type type
)
_

問題は、MyProtocol.GetType().FullNameを使用してオブジェクトタイプを永続化し、次の値が得られることでした。

Type protocolType = Type.GetType(PersistedTypeString);

nullの値を持つタイプになります。ただし、MyProtocol.GetType().AssemblyQualifiedNameを使用すると、すべてが正常に機能します(p.s.これは、Type.GetType()のドキュメントにも含まれています)

コードサンプルは次のとおりです。

_Type ProtocolType = Type.GetType(MetaData["ProtocolType"]);
var Protocol = JsonConvert.DeserializeObject(Data["Protocol"], 
                                             ProtocolType, 
                                             JsonProtocolPersister.DefaultSettings);
return (IProtocol)Protocol;
_
32
avanwieringen