为什么即使服务仍在引用DataContract,Dispose也会被调用?

11

我已经定义了下面这个实现了IDisposableDataContract

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

我调用以下服务方法,传递上述数据契约的实例:

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

BeginUpload的实现中,我只是将元数据保存在字典中,如下所示:

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

我的问题是,为什么即使我已经将实例保存在字典_Dict中,从这个方法返回后立即调用了Dispose()方法?

我已验证Dispose()方法被调用的是我保存在字典中的同一个实例,因为保存的对象的_Disposed变为true,即_Dict[sessionId]._Disposed变成了true

我的服务行为设置为:

[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]

你确定在调用Dispose(..)方法时,是在同一个实例上创建的吗?我的意思是,可能已经创建了该类的另一个实例,并且对那个实例调用了Dispose(..)方法。检查你获得Dispose(..)方法的实例的哈希码... - Tigran
@Tigran:我更新了我的问题,加入了以下内容:“我已经验证了Dispose()方法是在我保存在字典中的同一实例上调用的,因为对于保存的对象,_Disposed变为true。” - Nawaz
1个回答

16
它被处理掉了,因为这个对象“属于”WCF——它是从无中生出的对象实例,用作传递给您的方法的参数。而且,它足够聪明地观察到这个对象实现了IDisposable接口,所以一旦您的方法完成,它就会对其进行处理。
如果您想在方法完成后保留此对象的实例,则需要自己创建这样一个实例,并从一个实例复制相关的详细信息到另一个实例。
为什么即使我已经将该实例保存在字典_Dict中,Dispose()也被调用了?
因为Dispose模式与引用和垃圾收集无关。重要的是,每当对一个可处置对象的引用在多个方法/actor/agent之间传递时,“谁”负责在何时调用Dispose有一个协议。在这种情况下,“谁”是WCF基础设施。
更正 - 您可以通过在方法上添加OperationBehavior属性并将AutoDisposeParameters设置为false来更改此行为:
[OperationBehavior(AutoDisposeParameters=false)]
public Guid BeginUpload(FileMetadataBase fileMetadata)
{
    //...
    var metadata = 

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接