如何从可能实现 IEnumerable的对象中提取 MethodInfo.Invoke 参数
使用反射,我尝试在预期为某种类型的 IEnumerable 的对象上调用 Linq 方法 IEnumerable.FirstOrDefault() ,并返回结果对象。
我有以下类:
class MyClass : IEnumerable<MyOtherClass>
{
public IEnumerator<MyOtherClass> GetEnumerator() { yield return new MyOtherClass(); }
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
}
class MyOtherClass { }
这就是我尝试调用该方法并返回结果的方式:
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
将返回新的 MyOtherClass
,但它失败了,因为 methodInfo.Invoke
期望参数数组中有一个对象。
System.Reflection.TargetParameterCountException: '参数计数不匹配。'
我不知道要向此方法提供什么,也不知道我要提供什么,也不知道为什么我必须提供它。
如果我提供某些类型,则会出现以下异常:
System.ArgumentException:'Object of type 'System.RuntimeType'无法转换为类型'System.Collections.Generic.IEnumerable`1 [MyNamespace.MyOtherClass]'.'
其他线程似乎没有解决 MethodInfo
调用的问题,或者假定要提供的类型MakeGenericMethod
在设计时可用,或者将 MethodInfo.Invoke
的参数数组指定为 null 或空。
我欢迎任何帮助理解这个问题的帮助,并且假设我用于查找泛型类型作为类型参数提供给 MakeGenericMethod
的代码至少在功能上是正确的,我应该向 methodInfo.Invoke 提供什么
,为什么?
return methodInfo.Invoke(objectThatIsExpectedToImplementIEnumerableT, new object[] { ??? });
Using reflection, I am trying to invoke Linq method IEnumerable.FirstOrDefault() on an object that is expected to be IEnumerable of some type, and return the result object.
I have the following classes:
class MyClass : IEnumerable<MyOtherClass>
{
public IEnumerator<MyOtherClass> GetEnumerator() { yield return new MyOtherClass(); }
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
}
class MyOtherClass { }
This is how I attempted to invoke the method and return the result:
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[] { });
}
I expected that supplying a new MyClass
to this method would return a new MyOtherClass
, but it fails because methodInfo.Invoke
expects a single object in the parameter array.
System.Reflection.TargetParameterCountException: 'Parameter count mismatch.'
I do not know what to supply to this method, or understand what I am supplying, or why I should have to supply it at all.
If I supply some type, I get the following exception:
System.ArgumentException: 'Object of type 'System.RuntimeType' cannot be converted to type 'System.Collections.Generic.IEnumerable`1[MyNamespace.MyOtherClass]'.'
Other threads seem not to address the question of a MethodInfo
's invocation, or presume the type to supply to MakeGenericMethod
is available at design time, or else give MethodInfo.Invoke
's parameter array as null or empty.
I would welcome any help in understanding this problem and, assuming my code for finding the generic type to supply as type arguments to MakeGenericMethod
is at least functionally correct, what I should supply to methodInfo.Invoke
, and why?
return methodInfo.Invoke(objectThatIsExpectedToImplementIEnumerableT, new object[] { ??? });
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
FirstOrDefault 是一个扩展方法,您需要将
this
作为参数传递FirstOrDefault is an Extension method, you need to pass
this
as an arg你根本不需要为此进行反思。
IEnumerable
继承自IEnumerable
,您可以使用从
IEnumerable
获取IEnumerable
You don't need reflection at all for that.
IEnumerable<T>
inherits fromIEnumerable
, and you can getIEnumerable<object>
fromIEnumerable
usingCast<T>()
: