2012-08-03 11 views
7

मेरे पास एक विशेष स्थिति है जहां मुझे अपवादों को फँसाने और अपवाद के स्थान पर क्लाइंट को ऑब्जेक्ट वापस करने की आवश्यकता है। मैं एक उच्च स्तर पर अपवाद हैंडलिंग तर्क डाल सकता हूं यानी एक कोशिश खंड के भीतर Foo लपेटें।मैं इस अपवाद हैंडलिंग कोड को DRY सिद्धांत का पालन कैसे कर सकता हूं?

कुछ नमूना कोड के साथ प्रदर्शन करना सबसे अच्छा है। अपवाद हैंडलिंग तर्क विधि के इरादे को ढका रहा है और यदि मेरे पास है, तो फू क्लास में, इसी तरह के इरादे के कई तरीके हैं, मुझे लगता है कि मैं खुद को पकड़ने के अधिकांश तर्क को दोहराता हूं।

नीचे दिए गए कोड में सामान्य अपवाद कार्यक्षमता को लपेटने के लिए सबसे अच्छी तकनीक क्या होगी?

public class Foo 
{ 
    public Bar SomeMethodThatCanThrowExcepetion() 
    { 
      try 
      { 
       return new Bar().Execute(); 
      } 
      catch(BazException ex) 
      { 
       WriteLogMessage(ex, Bar.ErrorCode); 
       return new Bar() { ErrorMessage = ex.Message, ErrorCode = Bar.ErrorCode;}     
      } 
    } 

    public Baz SomeMethodThatCanThrowExcepetion(SomeObject stuff) 
    { 
      try 
      { 
       return new Baz(stuff).Execute(); 
      } 
      catch(BazException ex) 
      { 
       WriteLogMessage(ex, Baz.ErrorCode); 
       return new Baz() { ErrorMessage = ex.Message, ErrorCode = Baz.ErrorCode;}     
      } 
    } 
} 
+0

क्या आप अपना अपवाद केवल एक और स्तर को ऊपर नहीं रख सकते थे और श्रृंखला को अपवाद फेंक सकते थे? – ametren

+0

दुर्भाग्य से, मैं नहीं कर सकता। मैं यहां प्रतिबंधित हूं। – fin

+0

क्या 'बार' और 'बाज' के बीच कोई आम आधार वर्ग है? – Lee

उत्तर

5

ली की टिप्पणी प्रति अपडेट किया गया


एक संभावना यह एक सामान्य सहायक विधि का उपयोग करने के लिए है। कुछ इस तरह:

public interface IError 
{ 
    public string ErrorMessage { get; set; } 
    public int ErrorCode { get; set; } 
} 

T TryExecute<T>(Func<T> action, int ErrorCode) where T : IError 
{ 
    try 
    { 
     return action(); 
    } 
    catch (Exception ex) 
    { 
     result = Activator.CreateInstance<T>(); 
     result.ErrorMessage = ex.Message; 
     result.ErrorCode = ErrorCode; 
     return result; 
    } 
} 

तब आप उपयोग करेंगे:

T TryExecute<T>(Func<T> action, int ErrorCode) 
{ 
    try 
    { 
     return action(); 
    } 
    catch (Exception ex) 
    { 
     result = Activator.CreateInstance<T>(); 
     typeof(T).GetProperty("ErrorMessage").SetValue(result, ex.Message, null); 
     typeof(T).GetProperty("ErrorCode").SetValue(result, ErrorCode, null); 
     return result; 
    } 
    return result; 
} 

आप बार और संशोधित कर सकते हैं, तो बाज, तो आप पर एक आवश्यकता रखकर टी द्वारा इस सुधार सकता है:

return TryExecute<Bar>(new Bar().Execute, Bar.ErrorCode); 

और:

return TryExecute<Baz>(new Baz(stuff).Execute, Baz.ErrorCode); 

यह आपके विशेष डिजाइन के लिए अति-अवशोषण हो सकता है या नहीं; शैतान विवरण में है।

+0

अगर कोई अपवाद – Lee

+0

पर फेंक दिया गया है तो यह शून्य हो जाता है @ विचार * * कैश * ब्लॉक के भीतर * ऑब्जेक्ट * त्रुटि ऑब्जेक्ट को सेट करने के लिए था। – McGarnagle

+0

ठीक है आप इसे 'टी' या किसी एक बनाने के किसी भी तरीके पर बिना किसी प्रतिबंध के कर सकते हैं। – Lee

2

क्या आपको वास्तव में हर विधि में स्पष्ट लॉगिंग की आवश्यकता है? प्रत्येक विधि में अपवाद तर्क रखने के बजाय, प्रोग्राम के Main विधि में एक हैंडलर रखें और अपवादों को सामान्य रूप से संभाल लें।

इसके अलावा, आपको पकड़ने वाले ब्लॉक से मनमाने ढंग से ऑब्जेक्ट वापस करने की आवश्यकता नहीं है, आपको वास्तव में लॉगिंग की आवश्यकता होनी चाहिए, बस इसे throw; का उपयोग करके इसे स्टैक को भटकने दें।

+1

मुझे सही जवाब की तरह लगता है, लेकिन सवाल में टिप्पणीकर्ता पूछता है कि वह किसी कारण से ऐसा करने से प्रतिबंधित है। – ametren

+0

प्रश्न में टिप्पणी देखें। मैं ऐसा करने से प्रतिबंधित हूं। सार्वजनिक इंटरफेस के रूप में कोसिडर फू और मेरे पास उस स्तर पर अपवाद को संभालने के लिए कोई नियंत्रण नहीं है। – fin

+1

ठीक है, जब मैंने अपना जवाब लिखा था तो वह जानकारी वहां नहीं थी। – Femaref

5

कैसे एक आधार वर्ग के बारे में:

public class ErrorCapable { 
    public string ErrorMessage { set; get; } 
    public int ErrorCode { set; get; } 

    public static ErrorCapable<T> Oops(Exception exc) where T : ErrorCapable, new() { 
    // Code for logging error here 
    return new T() { ErrorMessage = exc.Message, ErrorCode = exc.ErrorCode }; 
    } 
} 

public class Bar : ErrorCapable { 
    //... 
} 
public class Baz : ErrorCapable { 
    //... 
} 
तो पकड़ में

, बस उदाहरण के लिए उपयोग करते हैं,:

return ErrorCapable.Oops<Bar>(ex); 
2

मैं सबसे अच्छा आप कर सकते हैं लगता है कि कुछ की तरह:

public T TryOrDefault<T>(Func<T> act, int errorCode, Func<BazException, T> onError) 
{ 
    try 
    { 
     return act; 
    } 
    catch(BazException ex) 
    { 
     WriteLogMessage(ex, errorCode); 
     return onError(ex); 
    } 
} 

तो आप इसके संदर्भ में अपनी अन्य विधियां लिख सकते हैं:

public Bar SomeMethodThatCanThrowException() 
{ 
    Bar b = new Bar(); 
    return ExecOrDefault(() => b.Execute(), Bar.ErrorCode, ex => new Bar { ErrorMessage = ex.Message, ErrorCode = Bar.ErrorCode }); 
}