使用反射,我試圖在預期為某種型別的 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為這個方法提供一個 new 會回傳一個 new MyOtherClass,但它失敗了,因為methodInfo.Invoke需要引數陣列中的一個物件。
System.Reflection.TargetParameterCountException: 'Parameter count mismatch.'
我不知道為這個方法提供什么,或者理解我在提供什么,或者為什么我必須提供它。
如果我提供某種型別,我會得到以下例外:
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[] { ??? });
uj5u.com熱心網友回復:
FirstOrDefault 是一個擴展方法,您需要this作為引數傳遞
return methodInfo.Invoke(null, new object[] {objectThatIsExpectedToImplementIEnumerableT });
uj5u.com熱心網友回復:
你根本不需要反思。IEnumerable<T>繼承自IEnumerable,您可以IEnumerable<object>從IEnumerable使用中獲得Cast<T>():
object GetFirstItemFromObject(object objectThatIsExpectedToImplementIEnumerableT)
{
var enumerableObject = (IEnumerable)objectThatIsExpectedToImplementIEnumerableT;
return enumerableObject.Cast<object>().FirstOrDefault();
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/439482.html
