[英]Unable to cast object of type 'System.Object[]' to 'MyObject[]', what gives?
場景:
我正在編寫一個層來將3個類似的Web服務抽象為一個可用的類。 每個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的任何強制轉換都會起作用嗎?
基本上沒有。 數組協方差有一些有限的用法,但最好只知道你想要哪種類型的數組。 有一個通用的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; });
或者只是創建一個正確大小的新Property []並手動復制(或通過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及更高版本中,泛型通常比數組協方差更好。
替代答案:泛型。
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);
更干凈:)
正如其他人所說,陣列必須是正確的類型。 其他答案已經展示了如何在事實之后轉換真實對象[],但是您可以使用Array.CreateInstance創建正確類型的數組:
object[] result = (object[]) Array.CreateInstance(type, properties.Length);
假設type
是一個引用類型,這應該可以工作 - 數組的類型是正確的,但你只需要將它作為一個object[]
來填充它。
你不能像這樣轉換一個數組 - 它返回一個對象數組,它與一個對象不同。 嘗試Array.ConvertAll
這是正確的,但這並不意味着您可以將Object類型的容器轉換為其他類型的容器。 Object []與Object不同(盡管奇怪的是,你可以將Object []轉換為Object)。
在C#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(“PropertyName”)。
我還會使用泛型來指示SomeComplexObject的創建
T result = new T();
Type resultTypeRef = result.GetType();
但我說你不需要使用泛型。
不保證性能/效率,但確實有效。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.