1

Question:
Is there a static way to reliably determine the type contained by a type derived from CollectionBase, using Reflection or Microsoft.Cci?

Background:
I am working on a code generator that copies types, makes customized versions of those types, and converters between. It walks the types in the source assembly via Microsoft.Cci. It prints out source code using textual templates. It does a lot of conversion and customization, and tosses out code that I don't care about.

In my resulting code, I intend to replace List<T> everywhere that a CollectionBase, IEnumerable<T>, or T[] was previously used. I want to use List<T> because I am pretty sure I can serialize it without extra work, which is important for my application. T is concrete in every case. I am trying not to copy CollectionBase classes because I'd have to copy over the custom implementation, and I'd like to avoid having to do that in my code generator.

The only part I'm having a problem with is determining T for List<T> when replacing a custom CollectionBase.

What I've done so far:
I have briefly looked at the MSDN docs and samples for CollectionBase, and they mention creating a custom Add method on your derived type. I don't think this is in any way enforced, so I'm not sure I can rely on that. An implementor could name it something else, or worse, have a collection that supports multiple types, with Object as their only common ancestor.

Alternatives I have considered:
Maybe the default serialization does some tricks that I can take advantage of. Is there a default serialization for CollectionBase collections, or do you generally have to implement it yourself? If you have to do it yourself, is there some reliable metadata I could look at in order to determine the types? If it supports default serialization, does it rely on the runtime types of the items in the collection?

I could make a mapping in my code generator of known CollectionBase types, mapped to their corresponding T for List<T>. If a given CollectionBase type that I encounter isn't in the list, throw an exception. This is probably what I'll go with if I there isn't a reliable alternative.

Merlyn Morgan-Graham
  • 58,163
  • 16
  • 128
  • 183
  • Why is `CollectionBase` relevant here? Also, which version of Visual Studio are you targeting? See http://msdn.microsoft.com/en-us/library/cc901387(VS.90).aspx for how the `Cci` namespace has changed for VS2008. – John Saunders Jan 30 '11 at 23:43
  • @John: I'm targeting 3.5. I'm using the public 2.0-ish source off codeplex. `CollectionBase` is relevant because the source code has types derived from it, and I want my target code to change those properties and methods to use `List`. I've edited my question, so hopefully that important detail is clearer now :) – Merlyn Morgan-Graham Jan 30 '11 at 23:52
  • @Merlyn: What kind of serialization are you concerned about? I don't see a problem that would require you to change from `CollectionBase`. – John Saunders Jan 30 '11 at 23:52
  • @John: The solution I'm going for isn't to solve a serialization problem (though serialization is a requirement), it is to solve a dependency problem. I'm trying to recursively clone a set of services from an existing monolithic codebase so that I can remove dependencies on it wherever possible. I'm creating interfaces, and recursively making act-alike DTOs. The target interfaces are ASMX web services, which don't have a clean separate library for interfaces/DTOs. I can't check in changes to that code base, but expect that changes will come from other sources, hence a code generator. – Merlyn Morgan-Graham Jan 31 '11 at 00:06
  • @John: Is there a way to make a multiple service references *generate* shared base types (not reuse existing ones), then use `partial` to customize them? That would also solve my problem :) – Merlyn Morgan-Graham Jan 31 '11 at 00:09
  • @Merlyn: I'm still not sure enough about what you want to do to give advice. Still, do your `CollectionBase`-derived classes all implement `Add(T)`? If so, you could look for an `Add` method with single parameter of type other than `object`, and use that type for `T`. – John Saunders Jan 31 '11 at 00:39
  • @John: If you make your "Check for an add method" comment an answer, I'll accept it, since that's what I ended up doing :) – Merlyn Morgan-Graham Feb 14 '11 at 18:59

1 Answers1

0

I'm still not sure enough about what you want to do to give advice. Still, do your CollectionBase-derived classes all implement Add(T)? If so, you could look for an Add method with single parameter of type other than object, and use that type for T.

John Saunders
  • 160,644
  • 26
  • 247
  • 397