2008-10-17 50 views
10

方案:無法將'System.Object []'類型的對象轉換爲'MyObject []',給出了什麼?

我目前正在編寫一個圖層,將3個類似的webservices抽象爲一個可用的類。每個Web服務都公開一組共享公共性的對象。我創造了一套利用共同性的中介對象。但是在我的圖層中,我需要在Web服務對象和我的對象之間進行轉換。

我使用反射來在運行時創建相應的類型我做出像這樣的調用Web服務之前:

public static object[] CreateProperties(Type type, IProperty[] properties) 
    { 
     //Empty so return null 
     if (properties==null || properties.Length == 0) 
      return null; 

     //Check the type is allowed 
     CheckPropertyTypes("CreateProperties(Type,IProperty[])",type); 

     //Convert the array of intermediary IProperty objects into 
     // the passed service type e.g. Service1.Property 
     object[] result = new object[properties.Length]; 
     for (int i = 0; i < properties.Length; i++) 
     { 
      IProperty fromProp = properties[i]; 
      object toProp = ReflectionUtility.CreateInstance(type, null); 
      ServiceUtils.CopyProperties(fromProp, toProp); 
      result[i] = toProp; 
     } 
     return result; 
    } 

這裏是我的調用代碼,從我服務的實現方式之一:

Property[] props = (Property[])ObjectFactory.CreateProperties(typeof(Property), properties); 
_service.SetProperties(folderItem.Path, props); 

所以每個服務都暴露了一個不同的「Property」對象,我隱藏在我自己的IProperty接口實現後面。

反射代碼在單元測試中工作,產生元素屬於相應類型的對象數組。但調用的代碼失敗:

System.InvalidCastException:無法類型的 投對象System.Object的[]' 鍵入 「MyProject.Property []

任何想法?

我的印象是,只要包含的對象是可轉換的,任何來自Object的強制轉換都可以工作。

回答

9

替代答案:泛型。

public static T[] CreateProperties<T>(IProperty[] properties) 
    where T : class, new() 
{ 
    //Empty so return null 
    if (properties==null || properties.Length == 0) 
     return null; 

    //Check the type is allowed 
    CheckPropertyTypes("CreateProperties(Type,IProperty[])",typeof(T)); 

    //Convert the array of intermediary IProperty objects into 
    // the passed service type e.g. Service1.Property 
    T[] result = new T[properties.Length]; 
    for (int i = 0; i < properties.Length; i++) 
    { 
     T[i] = new T(); 
     ServiceUtils.CopyProperties(properties[i], t[i]); 
    } 
    return result; 
} 

然後調用代碼變爲:

Property[] props = ObjectFactory.CreateProperties<Property>(properties); 
_service.SetProperties(folderItem.Path, props); 

在C#中乾淨多了:)

4

你不能像這樣轉換數組 - 它返回一個與對象不同的對象數組。嘗試Array.ConvertAll

1

這是正確的,但這並不意味着您可以將Object類型的容器轉換爲其他類型的容器。一個Object []與Object不是同一個東西(儘管你可以奇怪地將Object []轉換爲Object)。

+0

那麼,要迂腐,Object [] *是*一個對象...所以演員陣容並不奇怪。一切都是.NET中的一個對象 – 2008-10-17 14:50:17

9

基本上沒有。陣列協方差有一些有限的用途,但最好簡單地知道你想要的陣列類型。有一個通用Array.ConvertAll這是很容易(至少,它更容易與C#3.0):

Property[] props = Array.ConvertAll(source, prop => (Property)prop); 

的C#2.0版本(意義相同)要少得多眼球友好:

Property[] props = Array.ConvertAll<object,Property>(
    source, delegate(object prop) { return (Property)prop; }); 

或者只是創建一個合適大小的新屬性[]並手動複製(或通過Array.Copy)。

作爲的事情,你可以與陣列協方差的例子:

Property[] props = new Property[2]; 
props[0] = new Property(); 
props[1] = new Property(); 

object[] asObj = (object[])props; 

這裏, 「asObj」 是仍然一個Property[] - 它它只是作爲訪問object[]。在C#2.0及以上版本中,泛型通常比數組協方差更好。

+0

謝謝,這是有效的。 convertall與copy的性能影響是什麼? – 2008-10-17 14:47:32

+0

ConvertAll每次都會涉及一個委託調用,其中 - 複製應該只使用Buffer中的Buffer.BlockCopy。所以複製應該更快。 ConvertAll更容易輸入(並適用於中小尺寸),並且更靈活:您可以進行非平凡的投影。 – 2008-10-17 14:49:24

+0

此外 - ConvertAll將應付轉換,而不是強制轉換; Array.Copy無法做到這一點,因爲不能保證原始和目標對象的大小相同(這對Buffer.BlockCopy來說是必需的) – 2008-10-17 14:52:50

5

正如其他人所說,陣列必須是正確的類型開始。其他答案已經說明了如何真正Object []轉換後的事實,但你可以創建正確類型的數組開始使用Array.CreateInstance

object[] result = (object[]) Array.CreateInstance(type, properties.Length); 

假設type是引用類型,這應該工作 - 該數組將是正確的類型,但您將其用作object[]來填充它。

1

2.0你可以做到這一點使用反射,而無需使用泛型和不知道所需的類型在編譯時間。

//get the data from the object factory 
object[] newDataArray = AppObjectFactory.BuildInstances(Type.GetType("OutputData")); 
if (newDataArray != null) 
{ 
    SomeComplexObject result = new SomeComplexObject(); 
    //find the source 
    Type resultTypeRef = result.GetType(); 
    //get a reference to the property 
    PropertyInfo pi = resultTypeRef.GetProperty("TargetPropertyName"); 
    if (pi != null) 
    { 
     //create an array of the correct type with the correct number of items 
     pi.SetValue(result, Array.CreateInstance(Type.GetType("OutputData"), newDataArray.Length), null); 
     //copy the data and leverage Array.Copy's built in type casting 
     Array.Copy(newDataArray, pi.GetValue(result, null) as Array, newDataArray.Length); 
    } 
} 

你會想一些代碼,從配置文件中讀取全部更換Type.GetType(「OutputData」)調用和的getProperty(「屬性名」)。

我也將使用一個通用的主宰SomeComplexObject

T result = new T(); 
Type resultTypeRef = result.GetType(); 

的創造,而是我說你並不需要使用泛型。

沒有性能/效率保證,但它確實有效。

相關問題