0

Обновление - Проблема, с которой я столкнулся, была ошибкой пользователя. См. Мой ответ ниже.SerializationException сериализация newtonsoft jobject с DataContractSerializer

У меня есть класс, который я хочу добавить в DataContract API WCF, который должен быть «обязательным агностиком»; то есть он должен поддерживать несколько привязок, включая BasicHttp и NamedPipe. Класс Я хочу добавить к контракту данных использует Newtonsoft.Json.Linq.JObject для хранения данных члена:

[DataContract] 
public class MyFacet 
{ 
    public MyFacet(string facetName) 
    { 
     Initialize(); 
     FacetName = facetName; 
    } 

    internal JObject JsonObject { get; private set; } 

    [OnDeserializing] // required for deserialization to init JsonObject 
    private void OnDeserializing(StreamingContext c) 
    { 
     Initialize(); 
    } 

    private void Initialize() 
    { 
     JsonObject = new JObject(); 
    } 
    [DataMember] 
    public string FacetName 
    { 
     get 
     { 
      return GetProperty<string>("facet"); 
     } 
     private set 
     { 
      SetProperty("facet", value); 
     } 
    } 

    public string ToJson() 
    { 
     return JsonObject.ToString(Newtonsoft.Json.Formatting.None); 
    } 

    public T GetProperty<T>(string key) 
    { 
     JToken value; 
     if (JsonObject.TryGetValue(key, out value)) 
     { 
      return value.Value<T>(); 
     } 
     return default(T); 
    } 

    public void SetProperty(string name, object value) 
    { 
     SetProperty(name, new JValue(value)); 
    } 

    internal void SetProperty(string name, JToken value) 
    { 
     JsonObject[name] = value; 
    } 
} 

По разным причинам я хотел бы сохранить этот класс как есть, если вообще возможное. Когда я пытаюсь сериализации этого класса с DataContractSerializer (в тестовом приложении), я получаю следующее сообщение об ошибке:

System.Runtime.Serialization.SerializationException: 
Type 'ConsoleTest.MyFacet' with data contract name 
'MyFacet:http://schemas.datacontract.org/2004/07/ConsoleTest' is not expected. 
Consider using a DataContractResolver or add any types not known statically to 
the list of known types - for example, by using the KnownTypeAttribute attribute 
or by adding them to the list of known types passed to DataContractSerializer. 

Который, по существу, имеет смысл для меня. Но, добавляя различные типы Newtonsoft, поскольку KnownTypes не работает, это приводит к ошибке «рекурсивного сбора данных». Я думаю, что у меня будет такая же проблема, если я попытаюсь реализовать DataContractResolver.

Я считаю, что я могу сериализовать JObject в XML с помощью сериализатора Newtonsoft. Похоже, у меня есть несколько вариантов:

  • Используйте IDataContractSurrogate и поставить десериализованный суррогат JObject
  • Использование IClientMessageFormatter для создания пользовательских Сериализация/десериализации
  • Как-то еще Configure/переопределять/сериализации «системы де 'использовать сериализатор Newtonsoft вместо или вместе с DataContractSerializer.

И, я беспокоюсь о необходимости поддержки различных привязок. Именованный канал использовал двоичную кодировку, и я не уверен, как это влияет на эту проблему сериализации - может быть, это означает, что я должен использовать суррогат?

+0

Из сообщения об ошибке - вы изучили [Generic Data Contract Resolver] (http://blogs.msdn.com/b/carlosfigueira/archive/2011/09/21/wcf-extensibility-data-contract-resolver .aspx)? –

+0

Я думаю, что DataContractResolver сделает что-то похожее на добавление KnownTypeAttributes, только он попытается сделать это в общем и во время выполнения. В моем случае я считаю, что DataContractSerializer просто не может десериализовать типы (например, JObject), даже если он знает, что они собой представляют. –

ответ

0

Оказывается, это была ошибка пользователя 100%. В моей тестовой жгуте сериализации я пропустил неправильный тип, когда создавал DataContractSerializer. На следующем рисунке показана ОШИБКА:

Console.WriteLine("serializing..."); 
MyFacet facet = new MyFacet("MyFacet"); 
// On the following line, I was passing the wrong type to the ctor. 
// Needed to pass "MyFacet" here, not "Person" 
//!ERROR 
DataContractSerializer serializer = new DataContractSerializer(typeof(Person));//!ERROR 
var settings = new XmlWriterSettings { Indent = true }; 
using (var writer = XmlWriter.Create(fileName, settings)) 
    serializer.WriteObject(writer, facet); 

Как только я исправил ошибку, класс в исходном столбце сериализовался просто отлично. Сообщение об ошибке, которое я изначально получал, действительно отбросило меня. Я предполагал, что есть что-то о JObject или одном из типов Newtonsoft, вызывающих проблему, когда на самом деле я, очевидно, даже не пытался сериализовать любой из этих типов.

0

Я думаю, KnownTypeне помощь - так как он должен только помочь «найти» тип, когда ФОС DataContractSerializer должен знать, как сериализации.

И это не так, потому что JObject не включает DataContract и DataMember атрибутов.

Если JObject является xml-сериализуемым, я бы предпочел использовать сериализацию xml вместо сериализации DataContract.

 Смежные вопросы

  • Нет связанных вопросов^_^