2012-04-02 13 views
6

Tengo un formulario de InfoPath que necesito deshabilitar condicionalmente sus eventos OnChange. Como no es posible vincular los controladores de eventos una vez que se haya cargado el formulario, me veo obligado a confiar en un contador global que indica si se debe ejecutar un evento OnChange. Dentro de cada evento OnChange, compruebo si SuppressEventsCount == 0 antes de realizar cualquier acción. Para suprimir eventos durante la ejecución de alguna función u otra, simplemente configuro SuppressEventsCount ++, y nuevamente cuando la función sale. El mayor problema al hacer esto es que no es una excepción segura. Así que tuve la brillante idea de envolver los SuppressEvents contador en una clase que implementa IDisposableImplementación de RAII en C#

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

Esto funciona, pero todavía no es tan ideal como C++ solución que no requiere el uso de la "usando" directiva en absoluto.

¿Hay alguna manera a cualquiera:

  1. Gatillo un destructor o alguna función del momento en que un objeto sale del ámbito, O
  2. Evitar que los SuppressEvents objeto de ser inicializado fuera de un "uso" directiva enteramente
+0

Consulte esta pregunta: http://stackoverflow.com/q/2101524/6345 (¿Es abusivo utilizar IDisposable y "usar" como medio para obtener "comportamiento de alcance" para la seguridad de excepciones?) –

Respuesta

2

En relación con la pregunta 2, podría ser posible obtener información dándolo proporcionando una interfaz diferente a los consumidores del código. En lugar de proporcionar una clase pública que implementa IDisposable, y con la esperanza de que lo envuelven en una using, se podría proporcionar un método estático que toma una función para ejecutar en un contexto "suprimida":

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

    private class SuppressActions : IDisposable { 
     ... 
    } 
} 

A continuación, los consumidores pueden utilizar este de la siguiente manera:

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

por supuesto, usted tiene que averiguar si este diseño es apropiado, ya que esto dará lugar a las llamadas de función adicionales, clases compilador genera y cierres etc.

6

No y no. using es lo más cercano que se puede llegar a RAII (más exactamente, estamos hablando de la liberación de recursos que sigue a un objeto RAII-idiom que está siendo destruido).

para responder a sus puntos más directa:

  1. IDisposable (y por extensión using) fue creado precisamente porque no hay manera de hacerlo en .NET.
  2. using es el azúcar sintáctica que se compila como try/finally y sólo requiere que el objeto es IDisposable, por lo que no puede distinguir entre el uso dentro de una sentencia using y fuera de ella.
0

para responder a sus dos preguntas:

  1. No, no lo hay, recolección de basura en .NET no es de naturaleza determinista
  2. No, no se puede, la cláusula using se traduce en una intente/finalmente bloquee el tipo de código, y en cualquier caso no puede detectar que está construido a partir de cualquiera de esas dos construcciones, en comparación con
0

Si puede pasar de C# a C++. NET (todavía 100% .NET si está compilado con clr: safe), entonces puede usar msclr :: auto_handle que actúa como un puntero inteligente como auto_ptr, etc ...

Lo que realmente hace detrás de la escena en IL es un montón de comandos try/fault pero esto es completamente invisible para el desarrollador y el usuario. Todo el proceso es simplemente mejor IMO.