0

次のサンプル コードを確認します。

namespace A
{
  [Serializable]
  internal class ComplexObject<T> : List<T>, IEquatable<ComplexObject<T>>
    where T : IEquatable<T>
  {
    private T m_state;

    internal T State
    {
      get { return m_state; }
      set { m_state = value; }
    }

    public bool Equals(ComplexObject<T> other)
    {
      // Implementation is omitted to save space.
    }
  }

  public static class Program
  {
    public static void Main()
    {
      var obj = new ComplexObject<int>();
      obj.State = 100;
      var stream = new MemoryStream();
      var serializer = new DataContractSerializer(obj.GetType());
      serializer.WriteObject(stream, obj);
      stream.Flush();
      stream.Seek(0, SeekOrigin.Begin);
      var copy = (ComplexObject<int>)serializer.ReadObject(stream);
      Debug.Assert(obj.Equals(copy));
    }
  }
}

ComplexObject<T>から派生することに注意してくださいList<T>

とにかく、最後のアサーションは失敗します。[Serializable]withを置き換えてto[CollectionDataContract]を付けても、同じ否定的な結果が得られます。[DataMember]m_state

クラスがコレクションであることにDataContractSerializer気づき、他の状態を無視することを選択したかのようです。

次のことを考慮して、この問題を解決する方法を誰かにアドバイスしてください。

  • ComplexObject<T>できるだけ変更を少なくしたい
  • DataContractSerializerこの質問とは関係のない理由で立ち往生しています

よろしくお願いします。

編集:

public bool Equals(ComplexObject<T> other)
{
  if (!m_state.Equals(other.m_state) || Count != other.Count)
  {
    return false;
  }

  bool result = true;
  for (int i = 0; i < Count && (result = this[i].Equals(other[i])); ++i)
  {
  }
  return result;
}
4

3 に答える 3

2

List 構造を正しくシリアル化するには、次のようにCollectionDataContract属性を使用する必要があります。

 [CollectionDataContract]
 [Serializable]
 internal class ComplexObject<T> : List<T>, IEquatable<ComplexObject<T>>
    where T : IEquatable<T> 

ただし、CollectionDataContract では、追加の DataMembers をシリアル化することはできません。回避策は、リストからの継承を回避することですが、代わりにメンバー変数にし、オプションで ICollection を次のように実装します。

[DataContract]
[Serializable]
internal class ComplexObject<T> : ICollection<T>, IEquatable<ComplexObject<T>>
  where T : IEquatable<T> 
{
    private T m_state;

    [DataMember]
    public T State
    {
        get { return m_state; }
        set { m_state = value; }
    }

    private List<T> m_List = new List<T>();

    [DataMember]
    public List<T> List
    {
        get { return m_List; }
        set { m_List = value; }
    }

    public bool Equals(ComplexObject<T> other)
    {
        if (!other.State.Equals(State))
            return false;

        if (other.List.Count != List.Count)
            return false;

        for (int i = 0; i < other.List.Count;i++)
        {
            if (!other.List[i].Equals(List[i]))
                return false;
        }

        return true;
    }

    // ICollection members left out to save space

    // helper methods to wrap around the List to decrease the amount
    // of refactoring work you would have to do
    public void Add(T item)
    {
        List.Add(item);
    }

    public bool Remove(T item)
    {
        return List.Remove(item);
    }

    public T this[int index]
    {
        get { return List[index]; }
    }
}
于 2009-12-01T20:48:38.680 に答える
1

問題は、オブジェクトの配列を返そうとしているときです-少なくとも私にとってはそうでした。

オブジェクトクラスのタイプのリストを作成する必要があることがわかりました。そのリストをに追加します。DataContractSerrializer(typeof(mylist));

したがって;

List<LinqtoSQLTableClass> mylist = new List<LinqtoSQLTableClass>();
DataContractSerializer(mylist.GetType());
StringBuilder sb = new StringBuilder();

var query = linqtosql blah blah

XmlWriter writer = XmlWriter.Create(sb);
            dcs.WriteObject(writer, query);        
            writer.Close();
于 2010-02-16T22:50:03.667 に答える
-1

オブジェクトを複製またはシリアル化するためのコードを次に示します。これと同じ問題があるかどうかを知りたいです。このコードは単純にオブジェクト型を返しますが、結果をオブジェクト型にキャストできます。

var serializer = new System.Runtime.Serialization.DataContractSerializer(GetType());
using (var ms = new System.IO.MemoryStream())
{
   serializer.WriteObject(ms, this);
   ms.Position = 0;
   return serializer.ReadObject(ms);
}
于 2009-12-01T20:23:08.910 に答える