Esposizione di un evento di smaltimento

2

Sto implementando una classe .NET che implementa IDisposable. Dopo essere stato eliminato, lo stato dell'oggetto non è valido e quindi nessuno dovrebbe accedervi, naturalmente.

Ci sono alcune situazioni in cui due sistemi essenzialmente indipendenti hanno accesso alla stessa istanza di questa classe. Uno essenzialmente "possiede" l'oggetto ma l'altro è incaricato di interagire con l'oggetto in modo persistente.

Se il "proprietario" sceglie di sbarazzarsi dell'oggetto chiamando Dispose su di esso, l'altro sistema deve saperlo perché altrimenti potrebbe provare a interagire con un oggetto non valido. Non è sempre conveniente che il proprietario informi l'altro sistema di interrompere l'utilizzo dell'oggetto, perché il proprietario stesso potrebbe non conoscere questo altro sistema.

Ho la classe che implementa una proprietà IsDisposed, ma ci sono situazioni in cui il polling diventa impraticabile e sarebbe preferibile che il "non-proprietario" riceva invece la notifica che l'oggetto è eliminato.

A tal fine ho pensato che implementare un evento Disposing sulla classe sarebbe stata una buona soluzione, ma questo porta ad alcune domande progettuali:

  • L'istanza considerata è già stata eliminata nel momento in cui viene generato l'evento? (La mia ipotesi sarebbe che dovrebbe essere considerato vivo fino a quando i conduttori non finiscono.)

  • Come dovrebbe reagire l'oggetto a un'ulteriore manipolazione che si verifica all'interno dei gestori di eventi? (La mia ipotesi è di reagire nel solito modo per un oggetto vivente poiché è ancora vivo.)

  • Cosa succede se un gestore stesso chiama Dispose sull'oggetto? (Potremmo o ignorare esplicitamente le chiamate rientranti o semplicemente supporre che i gestori ben educati non lo facciano.)

  • L'evento Disposed dovrebbe ancora essere sollevato nel caso in cui l'oggetto sia finalizzato senza essere stato eliminato in modo esplicito? (Non riesco a pensare a un caso di mano in cui un tale evento sarebbe effettivamente necessario, e sicuramente ha il potenziale per causare problemi.)

Mi chiedo se ci sia qualche saggezza consolidata su come questo schema debba essere progettato in generale, o su qualsiasi altro esempio di cui dovrei essere a conoscenza di dove è probabile il problema.

    
posta Kevin 19.03.2013 - 22:47
fonte

2 risposte

1

Linq to SQL ha avuto un problema correlato, che ha a che fare con la valutazione lazy. Se i dati sono stati richiesti dopo che DataContext è stato eliminato (cosa che può succedere se la query è ponderata), è stata generata un'eccezione.

La soluzione era di non disporre del contesto dati e consentire al garbage collector di raccoglierlo in modo naturale. Vedi link

In senso stretto, non è necessario il modello dispose a meno che non si disponga di risorse non gestite. Le risorse non gestite non vengono automaticamente ripulite dal garbage collector, quindi devi farlo tu stesso. Naturalmente, questo non ha impedito ad alcune persone molto intelligenti da abbracciare il modello using per divertimento e profitto.

Tutto ciò che ho detto, non vedo alcun motivo per cui non è possibile attivare un evento dal metodo Dispose (). È possibile passare l'oggetto in fase di eliminazione tramite il gestore eventi e, finché il gestore eventi non trattiene l'oggetto troppo a lungo, eliminare le risorse gestite quando il gestore restituisce.

    
risposta data 19.03.2013 - 22:52
fonte
1

Sono abbastanza sicuro che sia nelle Linee guida sulla progettazione di framework da qualche parte, ma quello che ho osservato è che ogni volta che un oggetto ti fornisce un Disposable, non interagisce più con esso. Di solito, esiste una chiamata al metodo statico responsabile della creazione e della consegna del disposable a te.

Ci sono due opzioni che hai qui:

  • Il tuo "proprietario" non dovrebbe mai esporre l'IDisposable e dovrebbe invece agire come un adattatore su di esso. (In altre parole, il client chiama il "proprietario" che quindi delega le chiamate a IDisposable).

  • Il tuo "proprietario" dovrebbe essere una fabbrica e dovrebbe solo essere responsabile della creazione di un'istanza di IDisposable, di eseguire qualsiasi configurazione aggiuntiva e di passarla al client senza mai memorizzarne un riferimento.

risposta data 19.03.2013 - 23:12
fonte

Leggi altre domande sui tag