如何使用反射确定通用数组元素的类型? [英] How to determine the type of an generic array element with reflection?

查看:48
本文介绍了如何使用反射确定通用数组元素的类型?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想要做的是没有泛型很简单.

What I'm trying to do is without generic types is simple.

SomeType[] s = new SomeType[5];
for(int i = 0; i < 5: i++){
  s[i]= new SomeType();
}

使用泛型这是我目前所拥有的.

Using generics this is what I have so far.

private static T TypeMapper<T>(dynamic handle) {

    if (typeof(T).IsArray)
    {
        Type elementType = typeof(T).GetElementType();
        int arrayLength = handle.Length;
        Array array = Array.CreateInstance(elementType, arrayLength);

//???  How to get the type of an generic array element
        Type typeOfthis = typeof(array[0]).GetElementType();

        for (int i = 0; i < arrayLength; i++)
        {
//??? How to create an instance from it.
            array[i] = new typeOfthis ();
        }


        T obj = (T)(object)array;
        return obj;
    }
    else
    {}

然后调用 TypeMapper 函数.

Then calling the TypeMapper function with.

dynamic t = new TextSpan[4];
var result = TypeMapper<TextSpan[]>(t)

如何获取通用数组元素的类型.

How can I get the type of an generic array element.

Type typeOfthis = typeof(array[0]).GetElementType();//Not Working

以及如何从中创建实例.

And how to create an instance from it.

array[i] = new typeOfthis ();

非常感谢您的帮助.

铷37溶液被标记为正确

Type typeofitem = array.GetType().GetElementType(); 

代替

Type typeOfthis = typeof(array[0]).GetElementType();

array.SetValue(Activator.CreateInstance(typeofitem), i);

代替

array[i] = new typeOfthis ();

也感谢这里的其他解决方案,但他们完全没有意识到我可以将 SomeType[]SomeType 作为 T 传递给 TypeMapper;(动态句柄).然后我可以从类型中派生它是否是数组并根据需要处理句柄.

Thanks also for the other solutions here, but they quite missing the point that I can pass SomeType[] or SomeType as T to TypeMapper<T>(dynamic handle). Then I can then derive from the type if it is an array or not and process the handle as needed.

离题它背后的原因是从 v8dotnet 包装器使用的 v8 中编组 javascript 类型,该包装器返回具有与动态对象相同行为的对象.我没有解释 InternalHandle 句柄 是什么,而是将其简化为动态以便于理解.

offtopic The long breath reason behind it is to marshal javascript types from v8 used by the v8dotnet wrapper which returns objects which have an equal behavior like dynamic objects.Instead of explaining what an InternalHandle handle is I reduced it to dynamic so that it is comprehensible.

推荐答案

当你有一个数组元素时,你就有了一个对象,它可以是与其他数组元素不同的类型(如派生类型).然后,您可以像处理任何独立对象一样获取单个元素数组的类型.

When you have an array element, you have an object, that can be a different type from other array elements (like a derived type). Then you can get the type of a single element array as you do for any standalone object.

你应该更换

Type typeOfthis = typeof(array[0]).GetElementType();

Type typeOfthis = array[0].GetType();

然而,当您想要创建任何类型的对象时,您可以简单地使用 Activator.CreateInstance 或从类型中检索一个 ConstructorInfo.替换

Whereas, when you want create an object of any type, you can simply using Activator.CreateInstance or retrieve one ConstructorInfo from the Type. Replace

array[i] = new typeOfthis ();

array[i] = Activator.CreateInstance(typeOfthis);

只为你知道..
- 请记住,Activator.CreateInstance 将尝试调用您传递给它的类型的无参数构造函数,那么该类型需要具有这样的构造函数.
- 您创建的对象需要与数组的 Element 类型兼容(可分配给它,就像派生类一样).
- 如果你事先知道数组的所有元素都是(或应该是)相同的类型,那么你不需要获取每个元素的类型;相反, typeof(T).GetElementType() 应该就足够了.
- 如果元素类型是一个类并且你不需要分配具体的值,因为它们是稍后分配的,或者你知道元素类型是struct,那么你不需要填充数组.

Just for you yo know..
- Remember that Activator.CreateInstance will try to call a parameterless constructor of the type you pass to it, then that type need to have such a constructor.
- The object you create need to be compatible with the array's Element type (assignable to it, like a derived class).
- If you know in advance that all elements of the array are (or should be) of the same type, then you don't need to get the type for each element; instead, typeof(T).GetElementType() should be enough.
- If the element type is a class and you don't need to assign concrete values because they are assigned later, or you know that the elementi type is struct, then you don't need to fill the array.

细节的一部分,如果你想创建一个新数组,给定它的长度和它的元素的(具体)类型,你可以尝试以下方法之一:

A part of that details, if you want to create a new array, given its length and the (concrete) type of its elements, you can try one of the following:

public static Array CreateAndFillArray(Type type, int length)
{
    var result = Array.CreateInstance(type, length);
    for (int ixItem = 0; ixItem < result.Length; ixItem++)
        result.SetValue(Activator.CreateInstance(type), ixItem);
    return result;
}
public static T[] CreateAndFillArray<T>(int length)
{
    var type = typeof(T);
    var result = new T[length];
    for (int ixItem = 0; ixItem < result.Length; ixItem++)
        result[ixItem] = (T)Activator.CreateInstance(type);
    return result;
}
public static T[] CreateAndFillArray<T>(int length)
    where T : new()
{
    var result = new T[length];
    for (int ixItem = 0; ixItem < result.Length; ixItem++)
        result[ixItem] = new T();
    return result;
}

问候,
丹尼尔.

Regards,
Daniele.

这篇关于如何使用反射确定通用数组元素的类型?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆