2012-07-09 5 views
9

Ich habe die folgenden DataContract definiert, die IDisposable implementiert:Warum wird Dispose bei DataContract aufgerufen, obwohl der Dienst sich noch darauf bezieht?

[DataContract] 
public class RegularFileMetadata : FileMetadataBase, IDisposable 
{ 
    bool _Disposed = false; //note this! 

    //... 

    protected virtual void Dispose(bool disposing) 
    { 
     if (!_Disposed) 
     { 
      //... 
      _Disposed = true; //note this too! 
     } 
    } 
    public void Dispose() 
    { 
     Dispose(true); 
     GC.SuppressFinalize(this); 
    } 
} 

Und ich rufe die folgende Service-Methode eine Instanz des obigen Daten Vertrages vorbei:

[OperationContract] 
[ServiceKnownType(typeof(RegularFileMetadata))] 
Guid BeginUpload(FileMetadataBase metadata); 

Bei der Implementierung von BeginUpload, habe ich einfach Speichern Metadaten in einem Wörterbuch wie:

Dictionary<Guid, RegularFileMetadata> _Dict; 

public Guid BeginUpload(FileMetadataBase fileMetadata) 
{ 
    //... 
    var metadata = fileMetadata as RegularFileMetadata; 
    Guid sessionId = Guid.NewGuid(); 
    _Dict.Add(sessionId, metadata); //metadata SAVED! 
    return sessionId ; 
} 

Meine Frage ist, sofort nach der Rückkehr von dieser Methode, warum Dispose() aufgerufen wird, obwohl ich die Instanz im Wörterbuch _Dict gespeichert habe?

Ich habe festgestellt, dass Dispose() Methode auf dem gleichen Instanz aufgerufen wird, die ich in meinem Wörterbuch gespeichert haben, als _Disposed wird true für die Objekt gespeichert, das heißt _Dict[sessionId]._Disposed wird true!

Der Service Verhalten meines Dienstes eingestellt ist, wie:

[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)] 
+0

Sind Sie ssure dass Dispose (..) auf der aufgerufen wird ** selbe ** Instanz, die du erstellt hast? Ich meine * kann sein * es wurde eine andere Instanz der Klasse erstellt und Dispose (..) wurde an * dieser * angerufen. Überprüfen Sie * Hashcode * der Instanz, die Sie erhalten Dispose (..) auf ... – Tigran

+0

@Tigran: Ja ... – Nawaz

+0

@Tigran: Ich aktualisierte meine Frage mit: * "Ich habe überprüft, dass Dispose() -Methode auf der aufgerufen wird dieselbe Instanz, die ich in meinem Wörterbuch gespeichert habe, da _Disposed für das gespeicherte Objekt wahr wird. "* – Nawaz

Antwort

14

Es angeordnet ist, weil das Objekt zu WCF „gehört“ - es aus der Luft die Objektinstanz erstellt, als Parameter zu übergeben, um Ihre Methode. Und es ist nett genug zu beobachten, dass dieses Objekt IDisposable implementiert, so dass es nach Abschluss der Methode entsorgt wird.

Wenn Sie möchten, dass sich eine Instanz dieses Objekts nach Abschluss der Methode aufhängt, müssen Sie eine solche Instanz selbst erstellen und relevante Details von einer Instanz zur anderen kopieren.

warum Dispose() genannt wird, obwohl ich die Instanz im Wörterbuch gespeichert haben _Dict

Da das Dispose Muster nichts mit Referenzen und Garbage Collection zu tun. Es kommt nur darauf an, dass immer dann, wenn Verweise auf ein einmaliges Objekt zwischen mehreren Methoden/Akteuren/Agenten ausgetauscht werden, eine Vereinbarung darüber getroffen wird, wer für den Aufruf Dispose verantwortlich ist und wann. In diesem Fall ist das "Wer" die WCF-Infrastruktur.


Korrektur - Sie dieses Verhalten durch Hinzufügen des OperationBehavior Attribut auf Ihre Methode ändern können, und Einstellung AutoDisposeParameters auf false:

[OperationBehavior(AutoDisposeParameters=false)] 
public Guid BeginUpload(FileMetadataBase fileMetadata) 
{ 
    //... 
    var metadata = 
+0

+1. Macht Sinn. :-) – Nawaz