JSON.NET десериализует объект с параметром Type

У меня есть следующая проблема, которую я не могу решить:

У меня есть разные классы, которые реализуют интерфейс с именем IProtocol. На данный момент они называются SimpleProtocol, ParallelProtocol. Я хотел сохранить этот объект, поэтому использовал JSON.NET, и все работает нормально. За исключением случаев, когда я пытаюсь их десериализовать, он отлично работает, когда я знаю тип, которым они должны быть, например:

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

Однако теперь я в ситуации, когда хочу загрузить данные JSON и получить IProtocol назад, но это, понятно, не разрешено JSON; Например, что-то вроде этого работает не:

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.JObject до IProtocol. Это странно, и я не знаю, как это решить.

Нельзя передать объект Type в общий метод, поэтому я в основном застрял здесь. Есть ли способ решить эту проблему, желательно без использования Reflection? Мне кажется, что это совершенно нормальный вариант использования.

Что я могу сделать, но для меня это немного "грязно", это создать простой класс-оболочку, который содержит в себе экземпляр IProtocol и сериализует/десериализует это?

Ответы

Ответ 1

Казалось, что мой первоначальный подход с использованием этого метода был прав в конце концов:

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;