如何用反射确定通用数组元素的类型?

时间:2015-02-20 08:30:03

标签: c# reflection

我尝试做的是没有通用类型很简单。

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

使用泛型这是我到目前为止所做的。

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函数
dynamic t = new TextSpan[4];
var result = TypeMapper<TextSpan[]>(t)

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

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

以及如何从中创建实例。

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<T>(dynamic handle)。 然后,我可以从类型派生,如果它是一个数组,并根据需要处理句柄。

offtopic 它背后的长呼吸原因是从v8dotnet包装器使用的v8编组javascript类型,它返回具有与动态对象相同的行为的对象。而不是解释InternalHandle handle是什么,我将它减少为动态,因此它是理解的。

2 个答案:

答案 0 :(得分:1)

你需要学习更多关于泛型的知识(以及一般的概括)。如果要使用类型的默认实例填充数组,可以使用:

void ConstructAll<T>(T[] array) where T : new()
{
  for (var i = 0; i < array.Length; i++)
  {
    array[i] = new T();
  }
}

然而,这并不是一个好主意。你想解决什么问题?为什么你认为使用dynamic是一个很好的解决方案?

答案 1 :(得分:1)

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

你应该替换

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

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

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

array[i] = new typeOfthis ();

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

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

部分详细信息,如果要创建新数组,给定其长度和元素的(具体)类型,可以尝试以下方法之一:

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;
}

的问候,
丹尼尔。