0

更新- 我在这里遇到的问题是用户错误。请看下面我的回答。

我有一个要添加到 WCF API 的 DataContract 的类,它应该是“绑定不可知的”;即,它应该能够支持多种绑定,包括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,我想我会遇到同样的问题。

我相信我可以使用 Newtonsoft 序列化程序将 JObject 序列化为 XML。看来我有几个选择:

  • 使用 IDataContractSurrogate 并提供 JObject 的反序列化代理
  • 使用 IClientMessageFormatter 创建自定义序列化/反序列化
  • 以其他方式配置/覆盖反序列化“系统”以使用 Newtonsoft 序列化程序代替 DataContractSerializer 或与 DataContractSerializer 一起使用。

而且,我担心必须支持各种绑定。命名管道使用二进制编码,我不确定这会如何影响这个序列化问题——也许这意味着我必须使用代理?

4

2 回答 2

0

我认为,KnownType 不会有帮助 - 因为它应该只有助于“找到”类型,而 wcfDataContractSerializer应该知道如何序列化。

它没有,因为JObject不包含DataContractDataMember属性。

如果JObject是 xml 可序列化,我会考虑使用 xml 序列化而不是 DataContract 序列化。

于 2013-04-18T09:46:58.377 回答
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 类型之一的问题导致了这个问题,而事实上,我显然没有尝试序列化任何这些类型。

于 2013-04-19T05:41:50.173 回答