无法将’System.Object ‘类型的对象强制转换为’MyObject ‘,是什么给出的?

场景:

我正在编写一个层来将3个类似的Web服务抽象为一个可用的类。 每个Web服务都公开一组共享共性的对象。 我创建了一组利用共性的中间对象。 但是在我的图层中,我需要在Web服务对象和我的对象之间进行转换。

在调用Web服务之前,我已经使用reflection在运行时创建了相应的类型,如下所示:

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 eg 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接口实现之后。

reflection代码在unit testing中工作,生成一个对象数组,其元素的类型是合适的。 但是调用代码失败了:

System.InvalidCastException:无法将类型为’System.Object []’的对象强制转换为’MyProject.Property []

有任何想法吗?

我的印象是,只要包含的对象是可转换的,来自Object的任何强制转换都会起作用吗?

替代答案:generics。

 public static T[] CreateProperties(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 eg 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(properties); _service.SetProperties(folderItem.Path, props); 

更干净:)

基本上没有。 数组协方差有一些有限的用法,但最好只知道你想要哪种类型的数组。 有一个通用的Array.ConvertAll很容易(至少,使用C#3.0更容易):

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

C#2.0版本(意思相同)对眼球友好程度要低得多:

  Property[] props = Array.ConvertAll( 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及更高版本中,generics通常比数组协方差更好。

正如其他人所说,arrays必须是正确的类型。 其他答案显示了如何在事实之后转换真实对象[],但是您可以使用Array.CreateInstance创建正确类型的数组:

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

假设type是一个引用类型,这应该可以工作 – 数组的类型是正确的,但你只需要将它作为一个object[]来填充它。

你不能像这样转换一个数组 – 它返回一个对象数组,它与一个对象不同。 尝试Array.ConvertAll

这是正确的,但这并不意味着您可以将Object类型的容器转换为其他类型的容器。 Object []与Object不同(尽管奇怪的是,你可以将Object []转换为Object)。

在C#2.0中,您可以使用reflection完成此操作,而无需使用generics,也无需在编译时知道所需的类型。

 //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”)。

我还会使用generics来指示SomeComplexObject的创建

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

但我说你不需要使用generics。

不保证性能/效率,但确实有效。