如何从可能实现 IEnumerable<T> 的对象中提取 MethodInfo.Invoke 参数

How to extract MethodInfo.Invoke parameters from an object maybe implementing IEnumerable<T>

使用反射,我试图在预期为某种类型的 IEnumerable 的对象上调用 Linq 方法 IEnumerable.FirstOrDefault(),并 return 结果对象。

我有以下 类:

class MyClass : IEnumerable<MyOtherClass>
{
    public IEnumerator<MyOtherClass> GetEnumerator() { yield return new MyOtherClass(); }
    IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
}

class MyOtherClass { }

这就是我尝试调用该方法和 return 结果的方式:

object GetFirstItemFromObject(object objectThatIsExpectedToImplementIEnumerableT) 
{
    Type genericType = 
        objectThatIsExpectedToImplementIEnumerableT
        .GetType()
        .GetInterfaces()
        .Where(@interface => @interface.Name == "IEnumerable`1")
        .FirstOrDefault()
        ?.GenericTypeArguments
        ?.First()
        ?? throw new ArgumentException("Object does not implement IEnumerable<T>.");

    var methodInfo = 
        typeof(Enumerable)
        .GetMethods(BindingFlags.Public | BindingFlags.Static)
        .Where(methodInfo1 => methodInfo1.Name == "FirstOrDefault")
        .Select(method => method.MakeGenericMethod(new[] { genericType }))
        .FirstOrDefault()
        ?? throw new ArgumentException("Object does not have method member FirstOrDefault.");

    return methodInfo.Invoke(objectThatIsExpectedToImplementIEnumerableT, new object[] { });
}

我预计向该方法提供一个新的 MyClass 会 return 一个新的 MyOtherClass,但它失败了,因为 methodInfo.Invoke 需要参数数组中的单个对象.

System.Reflection.TargetParameterCountException: 'Parameter count mismatch.'

我不知道要为这个方法提供什么,或者不明白我要提供什么,或者我为什么要提供它。

如果我提供 some 类型,我会得到以下异常:

System.ArgumentException: 'Object of type 'System.RuntimeType' cannot be converted to type 'System.Collections.Generic.IEnumerable`1[MyNamespace.MyOtherClass]'.'

其他线程似乎没有解决 MethodInfo 的调用问题,或者假定提供给 MakeGenericMethod 的类型在设计时可用,或者给 MethodInfo.Invoke的参数数组为 null 或空。

我欢迎任何有助于理解这个问题的帮助,并且假设我找到泛型类型以作为类型参数提供给 MakeGenericMethod 的代码至少在功能上是正确的,我应该提供给 methodInfo.Invoke,为什么?

return methodInfo.Invoke(objectThatIsExpectedToImplementIEnumerableT, new object[] { ??? });

你根本不需要反思。 IEnumerable<T> 继承自 IEnumerable,您可以使用 Cast<T>():

IEnumerable 获取 IEnumerable<object>
object GetFirstItemFromObject(object objectThatIsExpectedToImplementIEnumerableT) 
{
    var enumerableObject = (IEnumerable)objectThatIsExpectedToImplementIEnumerableT;
    return enumerableObject.Cast<object>().FirstOrDefault();
}

FirstOrDefault 是一个扩展方法,您需要将 this 作为参数传递

return methodInfo.Invoke(null, new object[] {objectThatIsExpectedToImplementIEnumerableT });