Farhad Jabiyev
Farhad Jabiyev

Reputation: 26635

Create list of runtime-known type from object list and call generic method

I have IEnumerable<object> in memory.

Let's say this:

IEnumerable<object>() addedEntities = // ... some Linq-To-Object query

Also, I have a method with this signature:

public static IEnumerable<TSource> FilterByUniqueProp<TSource>
                (this IEnumerable<TSource> query, TSource model)
{
       // Do something according to this type
       var type = model.GetType();
}

As you see, this is an extension method. So, I can't dynamically call it, I must use MethodInfo for executing it in runtime.

In runtime, I must dynamically call this method for some Enumerable<T> of runtime-known type. But, it didn't matter what I did, it doesn't work. Either model.GetType() is always Object or exception is thrown.

Object of type 'System.Linq.Enumerable+WhereSelectArrayIterator2[System.Data.Objects.ObjectStateEntry,System.Object]' cannot be converted to type System.Collections.Generic.IEnumerable1[PersonDetail]'.

Here what I had tried:

 IEnumerable<object>() addedEntities = // ... some Linq-To-Object query

 Type listType = typeof(List<>);
 Type constructed = listType.MakeGenericType(model.GetType());
 dynamic myList = Activator.CreateInstance(constructed);
 myList = addedEntities;

 MethodInfo mesthod = typeof(DynamicLinqExtensions).GetMethod("FilterByUniqueProp");
 MethodInfo genericMethod= mesthod.MakeGenericMethod(model.GetType());
 dynamic sameEntitiesInContext = genericMethod.Invoke(this, new object[] { myList, model });

Upvotes: 0

Views: 807

Answers (1)

xanatos
xanatos

Reputation: 111860

Quite easy:

public static class DynamicLinqExtensions
{
    public static IEnumerable<TSource> FilterByUniqueProp<TSource>
            (this IEnumerable<TSource> query, TSource model)
    {
        // Do something accourding to this type
        var type = typeof(TSource);
        return null;
    }

    public static IEnumerable<TSource> FilterByUniqueProp2<TSource>
            (this IEnumerable<object> query, TSource model)
    {
        // We use Cast<>() to conver the IEnumerable<>
        return query.Cast<TSource>().FilterByUniqueProp<TSource>(model);
    }
}

You use .Cast<>!

Use it like:

// Your data
IEnumerable<object> addedEntities = new object[] { new MyClass(), new MyClass() };
object model = new MyClass();

// The needed code
Type type = model.GetType();

MethodInfo method = typeof(DynamicLinqExtensions)
          .GetMethod("FilterByUniqueProp2")
          .MakeGenericMethod(type);

method.Invoke(null, new object[] { addedEntities, model });

Note that in truth you could change directly the signature of FilterByUniquePropr to:

public static IEnumerable<TSource> FilterByUniqueProp<TSource>
        (this IEnumerable<object> query, TSource model)
{
    var query2 = query.Cast<TSource>();

    var type = typeof(TSource);

    return null;
}

and use reflection to call directl this method!

Upvotes: 1

Related Questions