I have defined the following DataContract
which implements IDisposable
:
[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);
}
}
And I call the following service method passing an instance of the above data contract:
[OperationContract]
[ServiceKnownType(typeof(RegularFileMetadata))]
Guid BeginUpload(FileMetadataBase metadata);
In the implementation of BeginUpload
, I simply save metadata in a dictionary as:
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 ;
}
My question is, immediately after returning from this method, why Dispose()
is called even though I've saved the instance in the dictionary _Dict
?
I have verified that Dispose()
method is called on the same instance which I have saved in my dictionary, as _Disposed
becomes true
for the saved object, i.e _Dict[sessionId]._Disposed
becomes true
!
The service behavior of my service is set as:
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
It's being disposed because that object "belongs" to WCF - it created the object instance out of thin air, to pass as a parameter to your method. And, it's kind enough to observe that this object implements IDisposable
, so it's disposing of it once your method completes.
If you want an instance of this object to hang onto after your method completes, then you need to create such an instance yourself, copying relevant details from one instance to the other.
why
Dispose()
is called even though I've saved the instance in the dictionary_Dict
Because the Dispose
pattern has nothing to do with references and garbage collection. All that matters is that, whenever references to a disposable object are being passed around between multiple methods/actors/agents, that there is an agreement on "who" is responsible for calling Dispose
and when. In this instance, the "who" is the WCF infrastructure.
Correction - you can alter this behaviour by adding the OperationBehavior
attribute to your method, and setting AutoDisposeParameters
to false:
[OperationBehavior(AutoDisposeParameters=false)]
public Guid BeginUpload(FileMetadataBase fileMetadata)
{
//...
var metadata =
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With