2012-04-02 10 views
6

Ho un modulo di InfoPath che mi serve per disabilitare in modo condizionale gli eventi OnChange. Poiché non è possibile associare i gestori di eventi dopo che il modulo è stato caricato, sono costretto a fare affidamento su un contatore globale che indica se un evento OnChange deve essere eseguito. All'interno di ogni evento OnChange, controllo se SuppressEventsCount == 0 prima di eseguire qualsiasi azione. Per sopprimere gli eventi durante l'esecuzione di una funzione o un'altra, ho semplicemente impostato SuppressEventsCount ++ e - di nuovo quando la funzione termina. Il più grande problema con questo è che non è sicuro. Così ho avuto la brillante idea di avvolgere le SuppressEvents contatore in una classe che implementa IDisposableImplementazione di RAII in C#

using(SuppressEvents s = new SuppressEvents()){ 
    // OnChange events fired here are ignored 
} // OnChange events enabled again 

Questo è il lavoro, ma non è ancora così ideale come soluzione di C++ che non richiede l'uso del "usando" direttiva affatto.

c'è qualche modo per uno:

  1. trigger un distruttore o qualche funzione del momento in cui un oggetto si passa nell'ambito, OR
  2. Prevenire gli SuppressEvents oggetto venga inizializzato al di fuori di un "tramite" direttiva interamente
+0

Vedere questa domanda: http://stackoverflow.com/q/2101524/6345 (È abusivo usare IDisposable e "using" come mezzo per ottenere "comportamento scoped" per la sicurezza delle eccezioni?) –

risposta

2

In relazione alla domanda 2, potrebbe essere possibile ottenere aroun d fornendo un'interfaccia diversa ai consumatori del codice. Invece di fornire una classe pubblica che implementa IDisposable, e sperando che avvolgerlo in un using, si potrebbe fornire un metodo statico che prende una funzione da eseguire in un contesto di "repressa":

public static class EventSuppressor { 
    public void Suppress(Action action) { 
     using (var s = new SuppressActions()) { 
      action(); 
     } 
    } 

    private class SuppressActions : IDisposable { 
     ... 
    } 
} 

Quindi i consumatori possono utilizzare questo come segue:

EventSuppressor.Suppress(() => { 
    // OnChange events fired here are ignored 
}) // OnChange events enabled again 

Naturalmente, è necessario capire se questo disegno è appropriato, come questo si tradurrà in chiamate aggiuntive di funzione, le classi compilatore ha generato e chiusure, ecc

6

No e no. using è il più vicino possibile a RAII (più precisamente, stiamo parlando del rilascio di risorse che segue un oggetto idioma RAII che viene distrutto).

Per rispondere alla tua punti più direttamente:

  1. IDisposable (e per estensione using) è stato creato proprio perché non c'è modo di farlo in .NET.
  2. using è zucchero sintattico che viene compilato come try/finally e richiede solo che l'oggetto è IDisposable, quindi non si può distinguere tra l'utilizzo all'interno di una dichiarazione using e fuori di esso.
0

per rispondere alle vostre due domande:

  1. No, non c'è, Garbage Collection in .NET non è deterministico in natura
  2. No, non è possibile, la clausola using si traduce in un prova/finalmente blocca il tipo di codice, e in ogni caso non puoi rilevare che è costruito da uno di questi due costrutti, rispetto a fuori
0

Se è possibile passare da C# a C++. NET (ancora 100% .NET se compilato con clr: safe), quindi è possibile utilizzare msclr :: auto_handle che agisce proprio come un puntatore intelligente come auto_ptr ecc ...

Ciò che fa realmente dietro la scena in IL è un sacco di comandi try/fault ma questo è completamente invisibile allo sviluppatore e all'utente. L'intero processo è semplicemente migliore IMO.