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

Rob*_*ett 11 .net c# arrays reflection casting

场景:

我正在编写一个层来将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;
    }
Run Code Online (Sandbox Code Playgroud)

这是我的调用代码,来自我的一个服务实现:

Property[] props = (Property[])ObjectFactory.CreateProperties(typeof(Property), properties);
_service.SetProperties(folderItem.Path, props);
Run Code Online (Sandbox Code Playgroud)

所以每个服务都公开一个不同的"Property"对象,我隐藏在我自己的IProperty接口实现之后.

反射代码在单元测试中工作,生成一个对象数组,其元素的类型是合适的.但是调用代码失败了:

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

有任何想法吗?

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

Mar*_*ell 9

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

Property[] props = Array.ConvertAll(source, prop => (Property)prop);
Run Code Online (Sandbox Code Playgroud)

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

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

或者只是创建一个正确大小的新Property []并手动(或通过Array.Copy)复制.

作为数组协方差可以做的事情的一个例子:

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

object[] asObj = (object[])props;
Run Code Online (Sandbox Code Playgroud)

在这里,"asObj" 仍然Property[]- 它只是简单地访问object[].在C#2.0及更高版本中,泛型通常比数组协方差更好.


Jon*_*eet 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;
}
Run Code Online (Sandbox Code Playgroud)

然后你的调用代码变成:

Property[] props = ObjectFactory.CreateProperties<Property>(properties);
_service.SetProperties(folderItem.Path, props);
Run Code Online (Sandbox Code Playgroud)

更干净:)


Jon*_*eet 5

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

object[] result = (object[]) Array.CreateInstance(type, properties.Length);
Run Code Online (Sandbox Code Playgroud)

假设type是一个引用类型,这应该工作 - 数组将是正确的类型,但你将使用它作为一个object[]只是填充它.