【问题标题】:How to determine the type of an generic array element with reflection?如何确定具有反射的泛型数组元素的类型?
【发布时间】:2015-02-20 19:07:32
【问题描述】:

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

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

题外话 其背后的长呼吸原因是编组来自 v8 的 javascript 类型,该类型由 v8dotnet 包装器使用,该包装器返回具有与动态对象一样的行为的对象。我没有解释InternalHandle handle 是什么,而是将其简化为动态的,以便它易于理解。

【问题讨论】:

  • 天啊。从哪儿开始。你到底想做什么?您已经提出了您的(无效的)解决方案,但是您的问题是什么?这看起来确实是一个错误的解决方案……嗯,几乎是任何问题。您只是在寻找return Enumerable.Range(1, 5).Select(i =&gt; new T()).ToArray() 吗?我看不出有任何理由在任何地方使用反射。 添加您的问题
  • array[0] return element 所以array[0].GetType() 足以获取元素类型

标签: c# reflection


【解决方案1】:

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

你应该替换

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

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

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

array[i] = new typeOfthis ();

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

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

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

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

问候,
丹尼尔。

【讨论】:

  • 最佳答案!!!但是一个小错误。用户 Type typeofitem = array.GetType().GetElementType(); 而不是 Type typeOfthis = array[0].GetType();
  • 你说得对:最好从数组的类型中获取元素类型;在您的示例中,您是通过“Type elementType = typeof(T).GetElementType();”完成的解决方案的第三个注释只是与它有关。显然,当方法接收 T 作为泛型数组类型时。 ;-)
【解决方案2】:

您需要了解更多有关泛型(以及一般泛化)的知识。如果你想用一个类型的默认实例填充一个数组,你可以使用这个:

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

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

【讨论】:

  • 如果你不能添加where T : new()约束:array[i] = Activator.CreateInstance&lt;T&gt;();代替
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-09-23
  • 1970-01-01
  • 2014-04-20
  • 2019-10-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多