सी # में डुप्लिकेट त्रुटि हैंडलिंग कोड को कम करना?

मैं अपवाद हैंडलिंग कार्यों के तरीके से पूरी तरह से खुश नहीं हूं, वहां बहुत सारे अपवाद हैं और टेबल पर आज़माएं / पकड़ें (अवांछित ढेर, इत्यादि), लेकिन ऐसा लगता है कि इस प्रक्रिया में ओओ मॉडल को तोड़ना है।

वैसे भी, यहां समस्या है:

आइए मान लें कि आपके पास कुछ वर्ग है जो नेटवर्क फ़ाइल फ़ाइल IO संचालन को लपेटता है या शामिल करता है (उदाहरण के लिए कुछ विशेष यूएनसी पथ पर कुछ फ़ाइल को पढ़ना और लिखना)। विभिन्न कारणों से आप नहीं चाहते हैं कि उन आईओ ऑपरेशंस असफल हो जाएं, इसलिए यदि आप यह पता लगाते हैं कि वे विफल हो जाते हैं तो आप उन्हें पुनः प्रयास करते हैं और आप सफल होने तक उन्हें पुनः प्रयास करते रहते हैं या आप टाइमआउट तक पहुंचते हैं। मेरे पास पहले से ही एक सुविधाजनक रेट्री टाइमर वर्ग है जिसे मैं तुरंत चालू कर सकता हूं और रीट्रीज़ के बीच वर्तमान धागे को सो सकता हूं और निर्धारित कर सकता हूं कि टाइमआउट अवधि कब समाप्त हो गई है।

समस्या यह है कि इस वर्ग के कई तरीकों से आपके पास आईओ ऑपरेशंस का एक गुच्छा है, और आपको उनमें से प्रत्येक को ट्राइक-कैच / रीट्री लॉजिक में लपेटने की ज़रूरत है।

यहां एक उदाहरण कोड स्निपेट है:

RetryTimer fileIORetryTimer = new RetryTimer(TimeSpan.FromHours(10));
bool success = false;
while (!success)
{
    try
    {
        // do some file IO which may succeed or fail
        success = true;
    }
    catch (IOException e)
    {
        if (fileIORetryTimer.HasExceededRetryTimeout)
        {
            throw e;
        }
        fileIORetryTimer.SleepUntilNextRetry();
    }
}

तो, आप कक्षा में हर फ़ाइल आईओ ऑपरेशन के लिए इस कोड के अधिकांश डुप्लिकेट से कैसे बचते हैं? मेरा समाधान अज्ञात प्रतिनिधि ब्लॉक और कक्षा में एक ही विधि का उपयोग करना था जिसने इसे पास किए गए प्रतिनिधि ब्लॉक को निष्पादित किया था। इसने मुझे अन्य तरीकों से इस तरह की चीजों को करने की अनुमति दी:

this.RetryFileIO( delegate()
    {
        // some code block
    } );

मुझे यह कुछ हद तक पसंद है, लेकिन यह वांछित होने के लिए बहुत कुछ छोड़ देता है। मैं सुनना चाहता हूं कि अन्य लोग इस तरह की समस्या को कैसे हल करेंगे।

0
जोड़ा
विचारों: 1
बस एक सामान्य एफवाईआई: यह लगभग हमेशा बेहतर फेंकने के बजाय throw; के बजाय
जोड़ा लेखक Dan Tao, स्रोत

4 उत्तर

बस सोच रहा है, आप अपनी विधि के पत्ते वांछित होने के लिए क्या महसूस करते हैं? आप अज्ञात प्रतिनिधि को एक के साथ बदल सकते हैं .. नाम? प्रतिनिधि, कुछ पसंद है

    public delegate void IoOperation(params string[] parameters);

    public void FileDeleteOperation(params string[] fileName)
    {
        File.Delete(fileName[0]);
    }

    public void FileCopyOperation(params string[] fileNames)
    {
        File.Copy(fileNames[0], fileNames[1]);
    }

    public void RetryFileIO(IoOperation operation, params string[] parameters)
    {
        RetryTimer fileIORetryTimer = new RetryTimer(TimeSpan.FromHours(10));
        bool success = false;
        while (!success)
        {
            try
            {
                operation(parameters);
                success = true;
            }
            catch (IOException e)
            {
                if (fileIORetryTimer.HasExceededRetryTimeout)
                {
                    throw;
                }
                fileIORetryTimer.SleepUntilNextRetry();
            }
        }
    }

    public void Foo()
    {
        this.RetryFileIO(FileDeleteOperation, "L:\file.to.delete" );
        this.RetryFileIO(FileCopyOperation, "L:\file.to.copy.source", "L:\file.to.copy.destination" );
    }
0
जोड़ा

यह पहलू ओरिएंटेड प्रोग्रामिंग पर एक नज़र डालने का एक शानदार अवसर दिखता है। .NET में AOP पर एक अच्छा लेख यहां दिया गया है । सामान्य विचार यह है कि आप क्रॉस-फ़ंक्शनल चिंता (यानी x घंटे के लिए पुनः प्रयास करें) को एक अलग वर्ग में निकाल देंगे और फिर आप किसी भी तरीके से एनोटेट करेंगे जो इस तरह से उनके व्यवहार को संशोधित करने की आवश्यकता है। यहां बताया गया है कि यह कैसे दिख सकता है (Int32 पर एक अच्छी विस्तार विधि के साथ)

[RetryFor( 10.Hours() )]
public void DeleteArchive()
{
  //.. code to just delete the archive
}
0
जोड़ा

आप एक और ओओ दृष्टिकोण का भी उपयोग कर सकते हैं:

  • एक बेस क्लास बनाएं जो त्रुटि प्रबंधन करता है और कंक्रीट काम करने के लिए एक सार विधि को कॉल करता है। (टेम्पलेट विधि पैटर्न)
  • प्रत्येक ऑपरेशन के लिए ठोस कक्षाएं बनाएं।

इसका आपके द्वारा किए जाने वाले प्रत्येक प्रकार के ऑपरेशन का नामकरण करने का लाभ होता है और आपको एक कमांड पैटर्न देता है - संचालन वस्तुओं के रूप में दर्शाया गया है।

0
जोड़ा

मैंने हाल ही में क्या किया है। यह शायद कहीं और बेहतर किया गया है, लेकिन यह बहुत साफ और पुन: प्रयोज्य लगता है।

मेरे पास एक उपयोगिता विधि है जो इस तरह दिखती है:

    public delegate void WorkMethod();

    static public void DoAndRetry(WorkMethod wm, int maxRetries)
    {
        int curRetries = 0;
        do
        {
            try
            {
                wm.Invoke();
                return;
            }
            catch (Exception e)
            {
                curRetries++;
                if (curRetries > maxRetries)
                {
                    throw new Exception("Maximum retries reached", e);
                }
            }
        } while (true);
    }

फिर मेरे आवेदन में, मैं चीजों को साफ रखने के लिए सी # के लैम्डा अभिव्यक्ति वाक्यविन्यास का उपयोग करता हूं:

Utility.DoAndRetry(() => ie.GoTo(url), 5);

यह मेरी विधि को कॉल करता है और 5 बार तक पुनः प्रयास करता है। पांचवें प्रयास में, मूल अपवाद को पुनः प्रयास के अंदर पुनर्स्थापित किया गया है।

0
जोड़ा
लेकिन कस्टम WorkMethod प्रतिनिधि <�कोड> एक्शन के बजाय प्रतिनिधि क्यों है?
जोड़ा लेखक Dan Tao, स्रोत