2012-04-02 27 views
6

Mam formularz InfoPath, który muszę warunkowo wyłączyć jego zdarzenia OnChange. Ponieważ nie można powiązać procedur obsługi zdarzeń po załadowaniu formularza, zmuszony jestem polegać na globalnym liczniku, który wskazuje, czy powinno zostać wykonane zdarzenie OnChange. Wewnątrz każdego zdarzenia OnChange, przed wykonaniem jakichkolwiek czynności sprawdzam, czy SuppressEventsCount == 0. Aby pominąć zdarzenia podczas wykonywania jakiejś funkcji lub innej, po prostu ustawę SuppressEventsCount ++, i - ponownie, gdy funkcja zostanie zakończona. Największym problemem jest to, że nie jest to wyjątek bezpieczny. Więc miałem jasną ideę zawinąć SuppressEvents przeciwdziałać w klasie, która implementuje IDisposableImplementacja RAII w C#

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

To działa, ale to nie jest jeszcze tak idealny jak C++ rozwiązanie, które nie wymaga korzystania z „używając” dyrektywa w ogóle.

Czy istnieje jakiś sposób, aby albo:

  1. wywołać destruktor lub niektórych funkcji moment przedmiot wykracza poza zakres, OR
  2. zapobiec SuppressEvents obiekt przed zainicjowany poza o „używając” dyrektywa całkowicie
+0

Zobacz to pytanie: http://stackoverflow.com/q/2101524/6345 (Czy nadużycie polega na używaniu IDisposable i "użyciu" jako sposobu uzyskania "określonego zachowania" w celu zachowania wyjątkowego bezpieczeństwa?) –

Odpowiedz

2

W odniesieniu do pytania 2, może być możliwe uzyskanie aroun d przez zapewnienie innego interfejsu konsumentom kodu. Zamiast dostarczać publiczne klasy, która implementuje IDisposable i mając nadzieję, że owinąć go w using, można zapewnić statyczną metodę, która przyjmuje funkcję do wykonania w „stłumione” kontekstu:

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

    private class SuppressActions : IDisposable { 
     ... 
    } 
} 

Wtedy konsumenci mogą korzystać z tego w następujący sposób:

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

oczywiście, trzeba pracować, czy ten projekt jest właściwe, ponieważ spowoduje to dodatkowych wywołań funkcji, klas kompilatora generowane i zamknięć itp

6

Nie i nie. using jest najbliższy do RAII (dokładniej mówimy o wydaniu zasobów, które następuje po niszczeniu obiektu idiomu RAII).

Aby odebrać swoje punkty bardziej bezpośrednio:

  1. IDisposable (a co za tym idzie using) został stworzony dokładnie, ponieważ nie ma sposobu, aby to zrobić w .NET.
  2. using jest cukier syntaktyczny który pobiera kompilowane jako try/finally i wymaga jedynie, że obiekt jest IDisposable, więc nie można odróżnić użytku wewnątrz using oświadczenia i poza nim.
0

Aby odpowiedzieć na dwa pytania:

  1. Nie, nie ma, Garbage Collection w .NET nie jest deterministyczny charakter
  2. Nie, nie można, klauzula using zostaje przełożone na spróbuj/w końcu zablokuj typ kodu, a w każdym razie nie możesz wykryć, że jest on zbudowany z któregokolwiek z tych dwóch konstruktów, w porównaniu do zewnątrz
0

Jeśli możesz przejść z C# do C++ .NET (nadal 100% .NET, jeśli skompilowany z clr: safe), możesz użyć msclr :: auto_handle, który działa jak inteligentny wskaźnik, taki jak auto_ptr itp ...

To, co naprawdę dzieje się za sceną w IL, to garść poleceń try/fault, ale to wszystko jest całkowicie niewidoczne dla programisty i użytkownika. Cały proces jest po prostu lepszy IMO.