Monday, 15 June 2009

V2: WCF CollectionDataContract and DataMember attributes

Following Jeff's comment on the first version of this post, here are some explanations and a full class.

Q1. Why did I write "implement IEnumerable" twice?
A1. My original intention was to derive my class from ICollection<T>. Thus I had to implement IEnumerable and IEnumerable<T>.

Q2. Why do I bother to implement IEnumerable at all if the class is not "decorated" as IEnumerable?
A2. ICollection<T> "derives" from IEnumerable<T> and IEnumerable, so we have to implement both of them when writing a class that implements ICollection<T>

Here is a complete class:

 [DataContract]
  public class EntityCollectionWorkaround<EntityType> : ICollection<EntityType>
  {
    #region Constructor
    public EntityCollectionWorkaround()
    {
      Entities = new List<EntityType>();
    }
    #endregion

    [DataMember]
    public int AdditionalProperty { get; set; }

    [DataMember]
    public List<EntityType> Entities { get; set; }

    #region ICollection<T> Members

    public void Add(EntityType item)
    {
      Entities.Add(item);
    }

    public void Clear()
    {
      this.Entities.Clear();
    }

    public bool Contains(EntityType item)
    {
      return Entities.Contains(item);
    }

    public void CopyTo(EntityType[] array, int arrayIndex)
    {
      this.Entities.CopyTo(array, arrayIndex);
    }

    public int Count
    {
      get
      {
        return this.Entities.Count;
      }
    }

    public bool IsReadOnly
    {
      get
      {
        return false;
      }
    }

    public bool Remove(EntityType item)
    {
      return this.Entities.Remove(item);
    }

    public EntityType this[int index]
    {
      get
      {
        return this.Entities[index];
      }
      set
      {
        this.Entities[index] = value;
      }
    }
    #endregion

    #region IEnumerable<T> Members

    public IEnumerator<EntityType> GetEnumerator()
    {
      return this.Entities.GetEnumerator();
    }

    #endregion

    #region IEnumerable Members

    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
    {
      return this.Entities.GetEnumerator();
    }

    #endregion
  }


* This source code was highlighted with Source Code Highlighter.

2 comments:

Nostradomus said...

client side doesn't work. THe types are not the same. Any thoughts?

Boris Modylevsky said...

Are you using the evil "Add Service Reference" from the IDE feature?
When used with generics types it generates a class with a random name, which changes every rebuild of the server side. The solution is to create an assembly that holds shared classes, that used both on server and on client.