Question

I'm trying to build an object that looks something like this:

  public class MyObject
  {
    private IList<AnotherObject> items;
    public List<AnotherObject> Items
    {
      return items.AsEnumerable().ToList<AnotherObject>();
    }
  }

I'm using NHibernate as my DAL and have it mapping directly to the items field and all that works fine.

I'm also using Windows Workflow and the replicator activity doesn't work with the generic IList. (http://social.msdn.microsoft.com/Forums/en-US/windowsworkflowfoundation/thread/2ca74b60-fd33-4031-be4b-17a79e9afe63) This is basically forcing me to use the List<> wrapper instead of the IList<>. This of course breaks the direct NHibernate mapping as NHibernate's IList implementation can't be cast directly to a List.

** EDIT: The Windows Workflow requirement actually means I'm going to lose type-safe access to the list no matter what as it requires an IList.

Now the goal is to serialize/deserialize this object. This works fine with binary serialization but the underlying NHibernate proxy objects explode with nhibernate errors when I try to deserialize them.

So I tried xml serialization. The serialization works fine and gives me my nice concrete class definitions in the serialized xml file which strips out the nhibernate proxies completely. However, when attempting to deserialize this, I'm unable to add the items to the list as the items.AsEnumerable.ToList call won't let items get added to the underlying list via the .Add method.

Does anyone have any thoughts on this? Am I going about this the wrong way?

** EDIT: The NHibernate concrete class is NHibernate.Collection.Generic.PersistentGenericBag which does indeed implement IList directly. However, I lost all the type-safe benefits of the generic list. This puts me back in the realm of having to write a wrapper for each child object and I really wanted to avoid that if possible.

Was it helpful?

Solution

On option is to create your own CustomList implementation that is wrapper around an instance that implements IList

i.e:

public CustomList<AnotherObject> Items    
{      
    return new CustomList<AnotherObject>(items); 
}

i.e. when you add to your CustomList<T> it adds to the backing list.

It sounds like so long as your class implements IList as well as IList<T> you will be fine.

OTHER TIPS

Yes, unfortunately you can't go about it this way. Calling ToList() creates a brand new instance of the list, so when you add items to that instance they aren't going to be reflected in the original list (as you've clearly discovered).

I don't use NHibernate, but I would be curious to see if your container implements IList (the non-generic version). From the thread you referenced, it appears that System.Collections.IList is what's actually required (and that's implemented by List<T>, which is why it works). Does your container implement IList?

Can't you just cast it like this?

public class MyObject
{
    private IList<AnotherObject> items;
    public List<AnotherObject> Items()
    {
        return (List<AnotherObject>)items;
    }
}

Havent had the chanse to try it out, but I think it should work!

I think the NHibernate PersistentBag (non-generic) collection implements IList so you could type items as IList instead of IList<AnotherObject>. The link in your question states that the problem is that replicator requires an IList which List<T> implements but IList<T> does not (go figure).

Can it be cast to IEnumerable<T>? You could try this:

public class MyObject
{
    private IList<AnotherObject> items;
    public List<AnotherObject> Items
    {
        return new List<AnotherObject>items.Cast<AnotherObject>());
    }
    // or, to prevent modifying the list
    public IEnumerable<AnotherObject> Items
    {
        return items.Cast<AnotherObject>();
    }
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top