So today was a found-work day. I have a bunch of non-trivial code that relies on 4.5 features, and it took a fair amount of effort to refactor it. In particular, I was using dynamic all over the place in my serialization layer (as followers of this blog from early days might know). I always knew I would have to replace that for iOS compatibility, but I just didn't think I'd have to do it right now.
I was using 'dynamic' because I didn't know how else to handle this problem during deserialization:
- Create container type via Activator.CreateInstance (let's say it's a HashSet<int>).
- Now I have 'object container'.
- I deserialize the first entry in the HashSet, giving my 'object entry'.
- How do I add 'entry' to 'container' ?
I can't cast 'container' to ICollection<object>, because this interface is not contravariant. That means I can't substitute in types higher in the type hierarchy for the generic parameter. This only makes sense; if I could do that then I could violate the type safety of the container, and add, say, a NetworkSocket to my HashSet of ints.
There is a trick for this, though, as I discovered today. You can cast to just plain non-generic ICollection. That doesn't care what you do.
Leveraging that, I was able to scrub out all references to 'dynamic' from my code. On the down-side, my ContainerSerializers class, which was already one of the scarier classes in my code base, has gotten still worse. I started from a noble desire to share as much common serialization logic between container objects as possible, but this has led to some pretty weird entanglements.
I've also had to resort to some kind of hair-raising reflection to unpack the objects, e.g.:
else if( i_gtype == typeof(Queue<>) ) { stype.GetMethod("Enqueue").Invoke(i_collection, i_obj ); }
--because ICollection has no Add(object)--I can't just cast all these ICollection containers to their common type and then do an add. I have to get weird. Hope that works on iOS.
No comments:
Post a Comment
Note: Only a member of this blog may post a comment.