I have two types: let's call them A and B. A can be converted to B using an adapter method.
I then have a collection of A's in a List<A>
(it could be any collection type that supports IEnumerable<A>
).
I now want to convert from IEnumerable<A>
to IEnumerable<B>
. I know the Type
of each of A and B, and I have a method to convert an A into a B, but my method and/or class is not templated itself, so I do not have access to the template type; e.g. the T in IEnumerable<T>
.
I effectively want to write this ConvertCollection method, where I know "from" is of type IEnumerable<{something}>
:
object ConvertCollection(object from, Type fromType, Type toType, Converter converter);
My converter looks like this:
delegate object Converter(object from);
My attempt leaves me here:
object ConvertCollection(object from, Type fromType, Type toType, Converter converter)
{
return ((IEnumerable<object>)from).Select(converter);
}
which partly works. If I call it like this
ConvertCollection(new List<A>() { new A() }, typeof(A), typeof(B), AToBConverter);
the returned collection does contain a collection of Bs, but the collection itself is of type IEnumerable<object>
, not IEnumerable<B>
, because I don't know how to cast to IEnumerable<{toType}>
. (It matters because the result needs to be serialized).
I can attack it from the other end and create the correct return type like this:
var result = Activator.CreateInstance(typeof(List<>).MakeGenericType(toType));
// TODO: populate result here
return result;
but then the problem is that to achieve the TODO part, I need to call List<> methods on result, but I can't cast it to any type of List<>
because of Co/ContraVariance rules, so even though I know the type supports List<>
methods, I can't get at them to use them to populate the list; e.g. to use Add().
Is there a way to do this without using 'dynamic' and without too much reflection? I know I could locate and invoke the Add() method via reflection, but it seems like it shouldn't be necessary.
.NET 4.0 BTW
-- Clarification
As Euphoric correctly speculates, and I tried but rather badly failed to convey above, I know the types A and B at runtime, but I do not know them at compile time. Hence the direct use of generics is not an option. I do know that the collections (both supplied and as must be returned) implement the generic IEnumerable<>
. That is all fixed and outside my control. (I've adjusted the title accordingly).
** Edit 2: fixed some formatting causing <>
to not display (easy to accidentally omit the back-ticks!)