【问题标题】:Create list of runtime-known type from object list and call generic method从对象列表创建运行时已知类型列表并调用泛型方法
【发布时间】:2015-08-07 21:26:52
【问题描述】:

我在内存中有IEnumerable<object>

让我们这样说:

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

另外,我有一个带有这个签名的方法:

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

如您所见,这是一种扩展方法。所以,我不能动态调用它,我必须使用MethodInfo在运行时执行它。

在运行时,我必须为一些 runtime-known 类型的Enumerable&lt;T&gt; 动态调用此方法。 但是,不管我做什么,它都不起作用。 model.GetType() 总是 Object 或者抛出异常。

对象类型 'System.Linq.Enumerable+WhereSelectArrayIterator2[System.Data.Objects.ObjectStateEntry,System.Object]' cannot be converted to type System.Collections.Generic.IEnumerable1[PersonDetail]'。

这是我尝试过的:

 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 });

【问题讨论】:

  • IEnumerable&lt;&gt;中的类型都是单类型还是多类型?所有PersonDetail 也是如此,或者他们可以是一个PersonDetail 一个DogDetail
  • @xanatos 所有单一类型。
  • 等等...你有 model 对象,所以你可以检查它的类型,对吧?
  • @xanatos 是的,对。我知道我必须创建什么类型的通用列表。
  • @farhas 你甚至不需要创建List&lt;&gt;。查看答案。

标签: c# linq dynamic reflection


【解决方案1】:

很简单:

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);
    }
}

你使用.Cast&lt;&gt;

像这样使用它:

// 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 });

请注意,实际上您可以将FilterByUniquePropr 的签名直接更改为:

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

    var type = typeof(TSource);

    return null;
}

并使用反射直接调用此方法!

【讨论】:

  • 感谢您的回答。但是,它抛出异常Late bound operations cannot be performed on types or methods for which ContainsGenericParameters is true.
  • @FarhadJabiyev 你忘了把MakeGenericMethod() 放在某个地方
  • 谢谢,它有效。说实话,我忘了以某种方式使用Cast&lt;TSource&gt;。再次感谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-09-02
  • 1970-01-01
  • 1970-01-01
  • 2012-10-01
相关资源
最近更新 更多