【问题标题】:How to call extension method "ElementAt"of List<T> with reflection?如何通过反射调用 List<T> 的扩展方法“ElementAt”?
【发布时间】:2009-12-22 19:11:44
【问题描述】:

我有一个问题,在创建 List 类型的对象“oListType01”并将其分配给另一个类型为“object”的对象“oObjectType”之后,我无法再访问函数“ElementAt(1)”。我尝试使用反射,但我总是在“调用”方法中遇到异常(参数冲突)。有谁知道为什么? 米兰

MyClass01 oMy1 = new MyClass01();
oMy1._ID = "1";

MyClass01 oMy2 = new MyClass01();
oMy2._ID = "3";

IList<MyClass01> oListType01 = new List<MyClass01>();

oListType01.Add(oMy1);
oListType01.Add(oMy2);

object oObjectType = new object();

oObjectType = oListType01;

从这里 fowrads 只有对象 oObjectType 可用(在实际情况下,向上发生在单独的函数调用中)。在 VS oObjectType 中显示了我想通过反射访问的两个元素。

MethodInfo mInfo = typeof(System.Linq.Enumerable).GetMethod("ElementAt").MakeGenericMethod(typeof(object));
object oSingleObject = mInfo.Invoke(oObjectType, new object[] { 1 });

【问题讨论】:

  • 你为什么首先将它分配给一个对象?如果出于某种原因必须这样做,并且如果您在编译时知道列表将始终包含 MyClass01 实例的类型,那么您为什么不将其转换回 List,如下所示:(( List)oObjectType).ElementAt(1);
  • 请看一下“answer”,我在其中解释说 invoke 只能用于引用 oObjectType(不是 oListType01 也不是 MyClass01)。

标签: c# linq reflection extension-methods


【解决方案1】:

我会假设您有正当理由这样做,但这似乎有点不对劲。也就是说,这里有一些代码可以完成您正在尝试做的事情。

MethodInfo mInfo = typeof(System.Linq.Enumerable).GetMethod("ElementAt").MakeGenericMethod(typeof(MyClass01));
object oSingleObject = mInfo.Invoke(oObjectType, new object[] { oObjectType, 1 });

当我运行这段代码时,我得到了列表中的第二个元素。

【讨论】:

  • 请看一下“答案”,我在其中解释说,invoke 只能用于引用 oObjectType(而不是 oListType01)。
  • 我更改了代码,以便它在引用上调用。应该这样做。
  • 这对我有用,谢谢!请注意:mInfo.Invoke() 的第一个参数可以为空。我们调用的是静态方法,而不是实例方法上的方法。
【解决方案2】:

ElementAt 扩展方法可能在 IEnumerable 上,因此当您将列表视为对象时,扩展方法将不可用,除非您强制转换它。 ((List)oObjectType).ElementAt() 或 (oObjectType as List).ElementAt()。

不过,我不得不问一问,你为什么一开始就想这样做?让我感到震惊的是,这里有一些问题可以使用接口做得更干净一些。

【讨论】:

  • IEnumerable 扩展方法在 System.Linq.Enumerable 类上。
  • 来自 System.Linq.Enumerable 。 . . public static TSource ElementAt(this IEnumerable source, int index) { ... }
  • 请看一下上面我解释了约束的答案。
【解决方案3】:

如果我们可以安全地假设:

  • oObjectType 是一些 T 的 IEnumerable

然后这是从中提取项目的代码。

请注意,我非常想知道这是否是解决此问题的正确方法,但是您没有向我们提供足够的信息来帮助您确定是否有更好的方法,所以我们只是'剩下的只是按要求回答问题。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Diagnostics;

namespace ConsoleApplication2
{
    class MyClass01
    {
        public String _ID;

        public override string ToString()
        {
            return _ID;
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            MyClass01 oMy1 = new MyClass01();
            oMy1._ID = "1";

            MyClass01 oMy2 = new MyClass01();
            oMy2._ID = "3";

            IList<MyClass01> oListType01 = new List<MyClass01>();

            oListType01.Add(oMy1);
            oListType01.Add(oMy2);

            object oObjectType = new object();

            oObjectType = oListType01;

            Test(oObjectType);

            Console.In.ReadLine();
        }

        private static void Test(object oObjectType)
        {
            Type tObject = oObjectType.GetType();
            Debug.Assert(tObject.IsGenericType);
            Debug.Assert(tObject.GetGenericArguments().Length == 1);
            Type t = tObject.GetGenericArguments()[0];

            Type tIEnumerable = typeof(IEnumerable<>).MakeGenericType(t);
            Debug.Assert(tIEnumerable.IsAssignableFrom(tObject));

            MethodInfo mElementAt =
                typeof(Enumerable)
                .GetMethod("ElementAt")
                .MakeGenericMethod(t);

            Console.Out.WriteLine("o[0] = " +
                mElementAt.Invoke(null, new Object[] { oObjectType, 0 }));
            Console.Out.WriteLine("o[1] = " +
                mElementAt.Invoke(null, new Object[] { oObjectType, 1 }));
        }
    }
}

【讨论】:

    【解决方案4】:

    这和你的other question 非常相似,但是在这种情况下,静态 ElementAt 方法实际上需要两个参数。试试这个:

    object oSingleObject = mInfo.Invoke(null, new object[] { oObjectType, 1 });

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-10-01
      • 1970-01-01
      • 1970-01-01
      • 2018-01-15
      • 1970-01-01
      相关资源
      最近更新 更多