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 を使用してカスタムのシリアル化/逆シリアル化を作成する
  • DataContractSerializer の代わりに、または DataContractSerializer と共に Newtonsoft シリアライザーを使用するように、デシリアライゼーションの「システム」を何らかの方法で構成/オーバーライドします。

そして、さまざまなバインディングをサポートしなければならないことが心配です。名前付きパイプはバイナリ エンコーディングを使用していましたが、それがこのシリアライゼーションの問題にどのように影響するかはわかりません。サロゲートを使用する必要があるということでしょうか?

4

2 に答える 2

0

wcfがシリアル化する方法を知っている必要がある場合、型を「見つける」のに役立つだけなので、役に立たKnownType ないと思います。DataContractSerializer

属性JObjectが含まれていないDataContractため、そうではありません。DataMember

xml がシリアライズ可能である場合JObject、DataContract シリアライゼーションの代わりに xml シリアライゼーションを使用することを検討します。

于 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 に答える