2009-01-28 2 views
7

Ich muss einen komplexen Typ von einem Webservice zurückgeben und hatte die Klasse MyComplexType, die die Schnittstelle IMyComplexType implementiert, erstellt. Jetzt in meinem Webservice habe ich eine Methode, die ein Objekt zurückgeben soll, die IMyComplexType implementiert wie so:Kann man Schnittstellen von .net Webservices zurückgeben oder kann man nur konkrete Klassen zurückgeben?

[WebMethod] 
public IMyComplexType GetMyComplexType() 
{ 
    IMyComplexType myCt = new MyComplexType(); 
    ... 
    return myCt; 
} 

Alles kompiliert in Ordnung, aber wenn ich den Webservice laufen wirft es eine Ausnahme wie folgt:

System.NotSupportedException: Cannot serialize interface MyWebService.IMyComplexType. 

Ist das ist Design oder ich vermisse etwas. Kann ich meine Klasse oder mein Interface irgendwie so dekorieren? Muss ich alle Schnittstellen eliminieren und nur mit konkreten und vielleicht abstrakten Basisklassen arbeiten, um dies mit .net Webservices tun zu können?

Edit:

das ist die Schnittstelle I zu serialisiert versuche:

public interface ICustomer 
{ 
    long Id {get; set;} 
    string Name {get; set;} 
    string EmailAddress {get; set;} 
} 

Antwort

0

Es ist schon eine Weile, aber ich glaube, Sie brauchen nur machen Sie Ihre Schnittstellen erweitern ISerializable und es sollte alles gut sein.

+0

Dies erfordert wiederum, dass ich die ISerializable-Schnittstelle in allen meinen Klassen implementiere - während ich hoffte, in der Lage zu sein, zu serialisieren, ohne das zu tun. Ich brauche nur die öffentlichen Eigenschaften. Die Schnittstellen zu entfernen und nur die konkreten Klassen zu verwenden funktioniert gut, aber ist das eine Best-Practice? – Fadeproof

0

Sie müssen nicht implementieren ISerializable - einfach markieren die Schnittstelle mit dem Serializable Attribut sollte alles sein, was Sie tun müssen. Wenn Sie die Schnittstelle implementieren wollen, gehen Sie auf jeden Fall vor - es gibt Ihnen eine fein abgestimmte Kontrolle darüber, wie die Schnittstelle serialisiert wird. Aber ich würde mir vorstellen, dass die Standardimplementierung in Ordnung sein sollte. Stellen Sie außerdem sicher, dass alle Schnittstellenelemente serialisierbar sind.

[Edit] Ich habe nicht einmal gerade nachgedacht - es gibt keine Möglichkeit, dass Sie ISerializable implementieren können, während Sie versuchen, ein Iterface trotzdem zu serialisieren. Die Stelle, an der sich befinden würde, wäre auf benutzerdefinierten Typen, die eine benutzerdefinierte Serialisierung benötigen, die von der Schnittstelle verfügbar gemacht werden.

+0

Kann Serializable-Attribut nicht auf Schnittstellen setzen - nur auf Klassen, Enums usw. Ich gab das einen Versuch, aber kein Glück. Noch etwas, was du vorschlägst? Ich habe keine benutzerdefinierten Serialisierungsanforderungen. Ich versuche nur, die Dinge richtig zu zeigen - durch Schnittstellen und nicht durch konkrete Typen. Ist das mit .net ws unmöglich? – Fadeproof

+0

es klingt wie einer der Typen in Ihrer Schnittstelle ist nicht serialisierbar - können Sie Ihren Beitrag bearbeiten und den Code für die Schnittstelle hinzufügen? –

+0

Ok. Hinzugefügt die Schnittstelle. Gibt es eine Möglichkeit, dies zu tun, ohne ISerializable zu implementieren, da ich möchte, dass dies serialisiert wird, so wie es ist und keine benutzerdefinierten Anforderungen? – Fadeproof

2

Kurze Antwort ist nein, Sie können eine Schnittstelle nicht über einen WebService zurückgeben.

Lange Antwort ist, dass Sie das Verhalten erhalten können, das Sie wollen, aber es ist ein bisschen hacky. Die Lösung besteht darin, binäre Serialisierung zu verwenden. Also serialisieren Sie Ihren Typ in Bytes, lassen Sie die Web-Methode eine Reihe von Bytes zurück und dann auf der anderen Seite würden Sie die Bytes wieder zu Ihrem komplexen Typ deserialisieren.

Zum Beispiel

[WebMethod] 
public byte[] GetMyComplexType() 
{ 

    IMyComplexType myCt = new MyComplexType(); 
    ... 

    MemoryStream stream = new MemoryStream(); 
    IFormatter fmt = new BinaryFormatter(); 
    fmt.Serialize(stream, myCt); 
    stream.Flush(); 
    byte[] bytes = stream.ToArray(); 
    stream.Close(); 

    return bytes; 
} 

Sie müssen alles wieder am anderen Ende konvertieren.

byte[] bytes = service.GetMyComplexType(); 
MemoryStream stream = new MemoryStream(bytes); 
BinaryFormatter fmt = new BinaryFomatter(); 
MyComplexType myCt = fmt.DeSerialize(stream); 

Sie können sich wahrscheinlich das Deserialisierungsereignis up reinigen durch ein gattungsgemäßes Verfahren zu schaffen. Ich sollte hinzufügen, dass Sie sicherstellen müssen, dass Sie auf den komplexen Typ auf dem Client verweisen können.

Alternativ können Sie, wenn sie Ihre Schnittstellen sind, in abstrakte Klassen umwandeln. Dies funktioniert jedoch nicht, wenn die Klasse mehrere Schnittstellen implementieren soll (oder Sie bereits von einer anderen Klasse erben), da Sie nur eine Klasse erben können. Wenn Sie auf dem Client ein polymorphes Verhalten benötigen, müssen Sie das XmlInclude-Attribut verwenden.