2009-08-03 16 views
17

Mam klasę z wieloma metodami i chcę mieć jedną procedurę obsługi wyjątków dla nich wszystkich. Jest tak wiele z tych metod i mają różne parametry, że pisanie try/catch dla każdego z nich byłoby brzydkie.Jedna procedura obsługi wyjątków dla wszystkich wyjątków klasy KLASY

Czy znasz sposób, w jaki mogę to zrobić z obsługą wyjątków w klasie, która obsłuży je wszystkie.

UPDATE:


Wielu z was pyta mnie dlaczego. Powodem jest to, że nazywam źródło danych różnymi metodami. , więc moja klasa ma funkcje getData1, gedData2, getData3, getData4, ...., getDataN. Problem polega na tym, że nie ma możliwości sprawdzenia, czy połączenie jest nadal otwarte, a stworzenie nowego połączenia jest bardzo kosztowne. Próbuję ponownie użyć połączenia i jeśli połączenie z następnym połączeniem nie powiodło się, złapałem to i ponownie się połączę i spróbuję ponownie. Właśnie dlatego potrzebuję tego spróbować/złapać cały blok.

to zrobić dla wszystkich funkcji:

try{  
    datasource.getData() 
} 
catch(ConnectionException) 
{ 
    datasource.Connect(); 
    datasource.getData() 
} 

Dzięki

+0

wiem, że to jest stare pytanie, ale chciałem powiedzieć, że chociaż w większości się z odpowiedziami poniżej, które zostały przesłane w dniu zadawania pytania, są chwile, kiedy zdolność ta byłaby bardzo przydatna. Husayt opisał jeden z powyższych i znalazłem to pytanie, ponieważ mam inny scenariusz. Chociaż odpowiedź Jacka Allana nie działa w moim scenariuszu, przegłosowałem go, ponieważ jest on przydatny w innych sytuacjach i jest bardzo inteligentny, IMHO. To powiedziawszy, zanim użyjesz "rozwiązania" Jacka, upewnij się, że nie ma innego sposobu na ukształtowanie kodu, aby uniknąć tego wszystkiego. –

+0

Nie ma takiego mechanizmu - ani nie powinno być, IMHO. Nie jest to zgodne z przepływem sterowania. Nie ma znaczenia, że ​​to, co musisz zrobić, to "brzydkie". Nie ma znaczenia, że ​​rozwiązanie, które zrobiłeś, wymaga napisania dodatkowego kodu. Liczy się to, że będziesz w stanie napisać oprogramowanie, które będzie łatwe do zrozumienia i zachować je później, kiedy ty lub ktoś inny zapomnisz o oryginalnych szczegółach. Jeśli metoda musi coś zrobić, gdy wystąpi wyjątek, MUSI być coś w metodzie, która mówi, co robić. To coś dobrego. – ToolmakerSteve

+0

BTW, przejąłem to pytanie, ponieważ uważam to za WIELKIE pytanie. Jest to uzasadnione i użyteczne dla innych, aby CHCĘ to zrobić. Zrozumienie DLACZEGO nie ma sposobu, aby to zrobić, i zrozumienie, co należy zrobić (co już zrobiłeś, w twoim pytaniu, nawet jeśli ci się nie spodobał wynik), będzie przydatne dla innych. – ToolmakerSteve

Odpowiedz

19

Można użyć delegata przekazać kod Twojego metoda jest w jednym try catch jak w poniższym przykładzie:

private void GlobalTryCatch(Action action) 
    { 
     try 
     { 
      action.Invoke(); 
     } 
     catch (ExpectedException1 e) 
     { 
      throw MyCustomException("Something bad happened", e); 
     } 
     catch (ExpectedException2 e) 
     { 
      throw MyCustomException("Something really bad happened", e); 
     } 
    } 

    public void DoSomething() 
    { 
     GlobalTryCatch(() => 
     { 
      // Method code goes here 
     }); 
    } 
1

nie sądzę, że jest. Możesz przenieść próbę/catch do dzwoniącego, ale to nie jest dobry projekt. Może byłoby lepiej, aby oddzielić go do innej klasy i użyć odbicie zadzwonić metod, takich jak to:

public class MyClass {} 
public class MySafeClass { 
    public void CallMethod(string name, object[] param) { 
     Type t = typeof(MyClass); 
     MyClass mc = new MyClass(); 
     try { 
      t.GetMethod(name).Invoke(mc, param); 
     } 
     catch { 
      //...; 
     } 
    } 

}

ale nie należy! To nie jest dobra praktyka.

Inną metodą jest wciąż przy try/catch ale o jedną metodę rzucać wyjątki itp powrotem do użytkownika:

public class MyClass { 
    void DoException(string message) { 
     throw new Exception(message); 
    } 
} 

Ale nadal nie jest tak dobra opcja.

Nie rozumiem, dlaczego byłoby to brzydkie - nawet jeśli po prostu owinąć całą metodę w jednym spróbuj/catch z wiadomości. To może być wykonalne.

Lepszą opcją jest pozostawienie ich i przekazanie do rozmówcy, być może w wersji try/finally.

Nie jest trudno dokładnie spróbować wszystkiego, szczególnie z fragmentami w Visual Studio i SharpDevelop.

+0

Dzięki za odpowiedź. Może patrząc na aktualizację pytania, możesz zobaczyć moje powody. – husayt

1

To brzmi jak problem z projektem. Czy możesz dokładnie wyjaśnić, jakie wyjątki próbujesz złapać i dlaczego i możemy spróbować z tym pomóc.

+0

tak, prawdopodobnie muszę podać więcej kontekstu, sprawdź moją aktualizację na pytanie proszę. – husayt

1

Wyjątki nie są tak naprawdę powiązane z klasą, ale zorientowane na metodę/zestaw wywoływany. Obiekt nie powinien na ogół próbować obsługiwać wyjątków z własnych metod. To zależy od tych metod.

0

możesz chcieć zastosować metodę próbną/catch o Tobie, chociaż uważam to za poważne nadużycie w obsłudze wyjątków, z wyjątkiem tego, że chcesz dołączyć rejestrator lub coś takiego.

+0

Potrzebuję czegoś tylko dla tej klasy i zajmuję się tą klasą Thnks – husayt

12

nie mogę wymyślić żadnego powodu, dlaczego można korzystać z obsługi wszystkich wyjątków w klasie przy użyciu jednej metody (można rozwinąć? Jestem ciekaw ...)

W każdym razie, można użyć AOP (Programowanie z orientacją aspektu) techniki do wstrzykiwania (statycznie lub w czasie wykonywania) kodu obsługi wyjątków związanych z metodami klasy.

Istnieje biblioteka dobry zespół post-processing nazywa PostSharp które można skonfigurować za pomocą atrybutów metod w swojej klasie:

Możesz określić aspekt takiego (od strony PostSharp):

public class ExceptionDialogAttribute : OnExceptionAspect 
{ 
    public override void OnException(MethodExecutionEventArgs eventArgs) 
    { 
     string message = eventArgs.Exception.Message; 
     MessageBox.Show(message, "Exception"); 
     eventArgs.FlowBehavior = FlowBehavior.Continue; 
    } 
} 

A potem będziesz stosować atrybut z metodami, które chcesz oglądać na wyjątkami, tak:

public class YourClass { 

    // ... 

    [ExceptionDialog] 
    public string DoSomething(int param) { 
     // ... 
    } 
} 

Można także zastosować atrybut do całej klasy, podobnie jak to:

[ExceptionDialog] 
public class YourClass { 
    // ... 
    public string DoSomething(int param) { 
     // ... 
    } 
    public string DoSomethingElse(int param) { 
     // ... 
    } 
} 

ten będzie miał zastosowanie rady (kod obsługi wyjątków) do każdej metody w klasie.

+1

Dobra odpowiedź. Po prostu dla FYI, wygląda na to, że PostSharp zmienił podpis OnException na OnException (MethodExecutionArgs eventArgs) dla metody wirtualnej. – joshmcode

+0

Po prostu chciałem dodać do tego mój przypadek użycia, tworzę mod do gry. Jeśli zgłoszę wyjątek, którego nie złapałem, chciałbym, żeby mój mod wyrejestrował się i zarejestrował błąd (zamiast zawiesić grę). Jest to wygodne. –

Powiązane problemy