Обновление - Проблема, с которой я столкнулся, была ошибкой пользователя. См. Мой ответ ниже.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.
И, я беспокоюсь о необходимости поддержки различных привязок. Именованный канал использовал двоичную кодировку, и я не уверен, как это влияет на эту проблему сериализации - может быть, это означает, что я должен использовать суррогат?
Из сообщения об ошибке - вы изучили [Generic Data Contract Resolver] (http://blogs.msdn.com/b/carlosfigueira/archive/2011/09/21/wcf-extensibility-data-contract-resolver .aspx)? –
Я думаю, что DataContractResolver сделает что-то похожее на добавление KnownTypeAttributes, только он попытается сделать это в общем и во время выполнения. В моем случае я считаю, что DataContractSerializer просто не может десериализовать типы (например, JObject), даже если он знает, что они собой представляют. –