12 Stimmen

Objekt vom Typ 'System.Object[]' kann nicht in 'MyObject[]' umgewandelt werden, was ist los?

Szenario:

Ich schreibe gerade eine Schicht, um 3 ähnliche Webservices in eine brauchbare Klasse zu abstrahieren. Jeder Webservice stellt eine Reihe von Objekten zur Verfügung, die Gemeinsamkeiten haben. Ich habe eine Reihe von Zwischenobjekten erstellt, die diese Gemeinsamkeiten ausnutzen. In meiner Schicht muss ich jedoch zwischen den Webservice-Objekten und meinen Objekten konvertieren.

Ich habe Reflection verwendet, um den entsprechenden Typ zur Laufzeit zu erstellen, bevor ich den Webdienst wie folgt aufrufe:

    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;
    }

Hier ist mein Aufrufcode aus einer meiner Dienstimplementierungen:

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

Jeder Dienst stellt also ein anderes "Property"-Objekt zur Verfügung, das ich hinter meiner eigenen Implementierung der IProperty-Schnittstelle verstecke.

Der Reflection-Code funktioniert in den Unit-Tests und erzeugt ein Array von Objekten, deren Elemente vom entsprechenden Typ sind. Aber der aufrufende Code schlägt fehl:

System.InvalidCastException: Unable to Objekt vom Typ 'System.Object[]' in Typ MyProject.Property[]

Irgendwelche Ideen?

Ich hatte den Eindruck, dass jeder Cast von Object funktioniert, solange das enthaltene Objekt konvertierbar ist?

9voto

Marc Gravell Punkte 970173

Im Grunde genommen, nein. Es gibt einige wenige, begrenzte Verwendungen von Array-Kovarianz, aber es ist besser, einfach zu wissen, welche Art von Array Sie wollen. Es gibt eine generische Array.ConvertAll, die einfach genug ist (zumindest ist es einfacher mit C# 3.0):

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

Die (bedeutungsgleiche) C# 2.0-Version ist weit weniger augenfreundlich:

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

Oder erstellen Sie einfach ein neues Property[] mit der richtigen Größe und kopieren Sie es manuell (oder über Array.Copy ).

Als Beispiel für die Dinge, die Sie puede mit der Array-Kovarianz zu tun:

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

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

Hier ist "asObj" immer noch a Property[] - es ist einfach zugänglich als object[] . In C# 2.0 und höher sind Generika in der Regel eine bessere Option als Array-Kovarianz.

9voto

Jon Skeet Punkte 1325502

Alternative Antwort: Generika.

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;
}

Dann wird Ihre Vorwahl zur Vorwahl:

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

Viel sauberer :)

5voto

Jon Skeet Punkte 1325502

Wie bereits gesagt wurde, muss die Anordnung zunächst vom richtigen Typ sein. Die anderen Antworten haben gezeigt, wie man ein echtes object[] im Nachhinein konvertiert, aber man kann die richtige Art von Array erstellen, indem man Array.CreateInstance :

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

Angenommen, type ein Referenztyp ist, sollte dies funktionieren - das Array hat den richtigen Typ, aber Sie verwenden es als object[] nur um sie zu befüllen.

4voto

Tom Ritter Punkte 97450

Sie können ein Array nicht auf diese Weise konvertieren - es gibt ein Array von Objekten zurück, was sich von einem Objekt unterscheidet. Versuchen Sie Array.ConvertAll

1voto

TheSmurf Punkte 15101

Das ist richtig, aber das bedeutet nicht, dass man Container des Typs Object in Container anderer Typen umwandeln kann. Ein Object[] ist nicht dasselbe wie ein Object (obwohl man seltsamerweise Object[] in Object casten könnte).

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X