Transforming a generic list from one type to another type, where types are only known at runtime

advertisements

Essentially, I'm looking for a way to transform GenericList<TInput> to GenericList<TOutput>, where GenericList is a generic list of any type that implements a specific interface, and the types TInput and TOutput are only known at runtime.

Below is a snippet of a class and method that can perform this operation, where TInput and TOutput are supplied at compile time.

 // --------------------------------------------------------------------------------
 /// <summary>This class is an example snippet for transforming generic lists of different types.</summary>
 ///
 /// <remarks></remarks>
 // --------------------------------------------------------------------------------
 public abstract class GenericListHelper<TInput, TOutput>
  where TInput : IGenericObject, new()
  where TOutput : IGenericObject, new()
 {

  // --------------------------------------------------------------------------------
  /// <summary>This method takes in a generic list of an input type
  /// and transforms it a list of the output type.</summary>
  ///
  /// <param name="inputGenericList">The input list to transform to this list.</param>
  /// <param name="filterElements">Field and property values to exclude from transform.</param>
  // --------------------------------------------------------------------------------
  public static GenericList<TOutput> CreateList(GenericList<TInput> inputGenericList, NameObjectCollection filterElements)
  {
   if (inputGenericList != null)
   {
    GenericList<TOutput> outputGenericList = new GenericList<TOutput>();
    foreach (TInput loopItem in inputGenericList)
    {
     TOutput newItem = new TOutput();
     DataTransformHelper.TransformDataFromObject(loopItem, newItem, filterElements);
     outputGenericList.Add(newItem);
    }
    return outputGenericList;
   }
   return null;
  }
 }

Is there any way of doing something along these lines where TInput and TOutput can be supplied at runtime?

Using reflection in one form or another seems to be the path to get there.

Initially, I tried creating a constructor for GenericList<TInput> that would take a list of type TOutput as a parameter (then I could call Activator.CreateInstance to get the new list).

Alternatively, I tried invoking the above method through reflection, but since that method is flagged ContainsGenericParameters=true, and is flagged as IsGenericMethod=false, I was not able to invoke the method, either through a normal method.Invoke or through a generic method.Invoke (unable to call MakeGenericMethod).


Isn't that what SelectMany is all about? Say I have two lists of different types, listA, and listB, then listC is a new list, like:

var listC = listA.SelectMany(a => listB, (a, b) => new { a.PropertyA, b.PropertyB });

You said you don't know the types until runtime but that they implement a specific interface, so you don't have to use reflection. So in your case listA would be an IEnumerable and PropertyA and PropertyB would be some properties your interface exposes.

Or if you are using attributes as you mentioned in a comment you can use that where the anonymous type is being created.