将对象转换为IEnumerable <t>,其中T未知</t>

时间:2012-08-29 00:01:54

标签: c# reflection

我正在尝试使用Reflection并遇到以下情况。

在下面的代码中,我们假设'obj'可以是IEnumerable<>ICollection<>IList<>类型。

我想将此System.Object强制转换为IEnumerable<>始终(ICollection<>IList<>继承自IEnumerable<>),以便我想枚举收集和使用反射来编写单个项目。

这背后的动机是我只是想看看Serializers一般会如何序列化数据,所以我试图模拟那种情况,希望也能理解Reflection。

我想把对象强制转换为非通用的IEnumerable ,但是我认为这会导致不必要的对象装箱,当我们说IEnumerable<int>的实际实例时......我想对吗?

private void WriteGenericCollection(object obj)
    {
        Type innerType = obj.GetType().GetGenericArguments()[0];

        //Example: IEnumerable<int> or IEnumerable<Customer>
        Type generatedType = typeof(IEnumerable<>).MakeGenericType(innerType);

        //how could i enumerate over the individual items?
    }

2 个答案:

答案 0 :(得分:20)

好吧,因为在运行之前你不知道项目的实际类型,所以你不需要使用通用的IEnumerable<T>接口;只使用非泛型的IEnumerable(通用的一个继承自它):

private void WriteGenericCollection(object obj)
{
    IEnumerable enumerable = (IEnumerable)obj;
    foreach(object item in enumerable)
    {
        ...
    }
}

答案 1 :(得分:4)

你的问题充满了误解。让我们清理它们。

  

在下面的代码中,我们假设'obj'可以是类型   IEnumerable<>ICollection<>IList<>

如果确实如此,如果您知道可枚举的类型,那么编写该方法的更好方法是

private void WriteGenericCollection<T>(IEnumerable<T> obj)
{
    // ...
}
  

我想将此System.Object转发给IEnumerable&lt;&gt;总是   (无论如何ICollection&lt;&gt;和IList&lt;&gt;继承自IEnumerable&lt;&gt;),所以   我想枚举集合并使用反射   写个别项目。

在谈论接口时,“继承”不是一个正确的术语;它也可能给你错误的想法。接口最好被认为是契约:在考虑实现接口时,您只能决定按照作者的意图实现它,或者根本不实现它。

某些接口是其他接口的超集;他们的合同说“除了合同所说的其他任何东西之外,实施者必须这样做”。但是,继承中没有任何共享实现,因为接口没有任何共享。

“向下转换”也不是您在该方法中所做的正确术语。向下转换意味着转向更加派生的类;还有一个界面:

// Note: the method is still generic!
private void WriteGenericCollection<T>(object obj)
{
    var casted = (IEnumerable<T>)obj;
}
  

我想到将对象向下转换为非通用的IEnumerable,但是   以为这会导致不必要的对象装箱   让我们说IEnumerable的实际实例...我在想什么?

当且仅当对象是IEnumerable<T>且其中Tvalue type(数字类型,bool时才会发生enumstruct)。如果对象为某些已知的IEnumerable<T>实现T,那么您可以简单地将其强制转换为该T。如果IEnumerable未知,则转换为非通用{{1}}并获取可能的性能命中(在任何情况下都无法绕过它)。

如果您知道关于对象的 nothing ,您只需要使用反射(在这种情况下,您当然还需要为无法枚举的对象制定计划,否则为什么允许将它们传递给你的方法首先?)。