2012-09-07 58 views
3

我有一個我想要轉換爲SomeType []類型的List的集合。運行時不知道SomeType。將IList轉換爲SomeType []

這必須通過以下程序的簽名完成。

private object ConvertListToArray(IList collection) 
{ 
     // This does not work since SomeType is not known before runtime. 
     var convertedList = collection.Cast<SomeType>().ToArray(); 
     return convertedList; 
} 

注意,集合是IList的,但已知的是,具體類型是

 List<SomeType> 

返回集合的類型必須是SOMETYPE []的對象。

這怎麼辦?

+0

怎麼樣collection.ToArray();這不是在這裏製造詭計嗎? – Katalonis

+0

你會期望*代碼解決它需要'SomeType []'而不是'object []','String []'或'SomeOtherType []'嗎?如果集合包含「SomeType」和「SeomOtherType」,你會期望什麼?如果它是空的呢? –

+0

Katalonis - ToArray()是列表的擴展,但我有IList。 – Oyvind

回答

1
public static class ListExtensions 
{ 
    public static T[] ConvertToArray<T>(IList list) 
    { 
     return list.Cast<T>().ToArray(); 
    } 

    public static object[] ConvertToArrayRuntime(IList list, Type elementType) 
    { 
     var convertMethod = typeof(ListExtensions).GetMethod("ConvertToArray", BindingFlags.Static | BindingFlags.Public, null, new [] { typeof(IList)}, null); 
     var genericMethod = convertMethod.MakeGenericMethod(elementType); 
     return (object[])genericMethod.Invoke(null, new object[] {list}); 
    } 

} 
[TestFixture] 
public class ExtensionTest 
{ 
    [Test] 
    public void TestThing() 
    { 
     IList list = new List<string>(); 
     list.Add("hello"); 
     list.Add("world"); 

     var myArray = ListExtensions.ConvertToArrayRuntime(list, typeof (string)); 
     Assert.IsTrue(myArray is string[]); 
    } 
} 
+0

謝謝你的工作得很好。要使用它與任何列表,我使用 var myArray = ListExtensions.ConvertToArrayRuntime(list,list.GetType()。GetGenericArguments()[0]); – Oyvind

+0

我想upvote,但我的聲望低於15,所以我不能投票。 – Oyvind

+0

沒問題,很高興它的工作。 –

2

你可以用下面的執行做到這一點:

class Program 
{ 
    static void Main(string[] args) 
    { 
     // same type 
     var myCollection = new List<string> {"Hello", "World"}; 
     var array = (string[])myCollection.ConvertToArray(); 
     Console.WriteLine(array[0]); 

     // new type 
     var intList = new List<int> {1, 2, 3}; 
     var stringArray = (string[])intList.ConvertToArray(typeof(string)); 
     Console.WriteLine(stringArray[0]); 

     // mixed types 
     var ouch = new List<object> {1, "Mamma", 3.0}; 
     var result= (string[])ouch.ConvertToArray(typeof(string)); 
     Console.WriteLine(result[0]); 


    } 
} 

實施:

public static class ListExtensions 
{ 
    public static object ConvertToArray(this IList collection) 
    { 
     // guess type 
     Type type; 
     if (collection.GetType().IsGenericType && collection.GetType().GetGenericArguments().Length == 0) 
      type = collection.GetType().GetGenericArguments()[0]; 
     else if (collection.Count > 0) 
      type = collection[0].GetType(); 
     else 
      throw new NotSupportedException("Failed to identify collection type for: " + collection.GetType()); 

     var array = (object[])Array.CreateInstance(type, collection.Count); 
     for (int i = 0; i < array.Length; ++i) 
      array[i] = collection[i]; 
     return array; 
    } 

    public static object ConvertToArray(this IList collection, Type arrayType) 
    { 
     var array = (object[])Array.CreateInstance(arrayType, collection.Count); 
     for (int i = 0; i < array.Length; ++i) 
     { 
      var obj = collection[i]; 

      // if it's not castable, try to convert it 
      if (!arrayType.IsInstanceOfType(obj)) 
       obj = Convert.ChangeType(obj, arrayType); 

      array[i] = obj; 
     } 

     return array; 
    } 
} 
+0

我想他說''SomeType'在編譯時是不知道的。 – sloth

+0

@BigYellowCactus:我也更新了更多動態代碼的例子。 – jgauffin

+0

+1工作正常,我認爲 – sloth

0

你可以嘗試:

private T[] ConvertListToArray<T>(IList collection) 
    { 
    // This does not work since SomeType is not known before runtime. 
      var convertedList = collection.Cast<T>().ToArray(); 
      return convertedList; 
     } 
+0

問題是我在運行時沒有T. – Oyvind

+0

我不明白你的問題。如果在運行時你仍然沒有得到這種類型,我想這是無法解決的。但看着解決方案,我看到了問題:-) –

0

我張貼這是其他答案似乎有點冗長。我很確定這是否是OP正在尋找的東西。它爲我工作。

public static Array ConvertToArray(ICollection collection, Type type) 
{ 
    var array = Array.CreateInstance(type, collection.Count); 

    collection.CopyTo(array, 0); 

    return array; 
} 
相關問題