Vra

Ek het nog nooit heeltemal tevrede met die manier om uitsonderings te hanteer werke nie, daar is 'n baie uitsonderings en probeer / vangs bring na die tafel (stapel ontbinding, ens), maar dit lyk na 'n groot deel van die OO model in die breek proses.

In elk geval, hier is die probleem:

Kom ons sê jy het 'n paar klas wat vou of sluit netwerk lêer IO bedrywighede (bv lees en skryf 'n paar lêer op 'n sekere spesifieke UNC pad iewers). Om verskeie redes wat jy nie wil daardie IO bedrywighede om te misluk, so as jy op te spoor wat hulle nie jy hulle weer probeer en jy weer probeer hulle hou totdat hulle slaag of jy 'n time-out te bereik. Ek het reeds 'n gerieflike RetryTimer klas wat ek kan instansieer en gebruik om die huidige draad tussen Pogingen slaap en bepaal wanneer die uittelperiode verstryk het, ens.

Die probleem is dat jy 'n klomp van die IO bedrywighede in verskeie metodes van hierdie klas, en wat jy nodig het om elkeen van hulle draai in drie-vangs / weer probeer logika.

Hier is 'n voorbeeld kode uit:

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();
    }
}

So, hoe kan jy verhoed dat duplisering meeste van hierdie kode vir elke lêer IO werking regdeur die klas? My oplossing was om anoniem afgevaardigde blokke en 'n enkele metode in die klas wat die afgevaardigde blok geslaag om dit uitgevoer word gebruik. Dit het my toegelaat om dinge te doen soos dit in ander metodes:

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

Ek hou van hierdie ietwat, maar dit laat veel te wense oor. Ek wil graag om te hoor hoe ander mense hierdie soort van probleem sal oplos.

Was dit nuttig?

Oplossing

Dit lyk soos 'n uitstekende geleentheid om 'n blik op aspekte georiënteerd Programmering het. Hier is 'n goeie artikel oor AOP in NET . Die algemene idee is dat jy die kruis-funksionele kommer (maw weer probeer vir x ure) in 'n aparte klas wil onttrek en dan sou jy enige metodes wat nodig het om hul gedrag op dié manier te verander annoteer. Hier is hoe dit kan lyk (met 'n mooi uitbreiding metode op int32)

[RetryFor( 10.Hours() )]
public void DeleteArchive()
{
  //.. code to just delete the archive
}

Ander wenke

Net gewonder, wat voel jy jou metode laat te wense? Jy kan die anonieme afgevaardigde met 'n vervang .. genoem? delegeer, iets soos

    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" );
    }

Jy kan ook gebruik om 'n meer OO benadering:

  • Skep 'n basis klas wat die fout hantering doen en doen 'n beroep 'n abstrakte manier om die beton werk te verrig. (Sjabloon Metode patroon)
  • Skep beton klasse vir elke operasie.

Dit het die voordeel van die benaming van elke tipe van die operasie wat jy verrig en gee jou 'n opdrag patroon - bedrywighede is verteenwoordig as voorwerpe

.

Hier is wat ek onlangs gedoen het. Dit is waarskynlik elders beter gedoen, maar dit lyk mooi skoon en herbruikbare.

Ek het 'n nut metode wat lyk soos volg:

    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);
    }

Toe ek in my aansoek, ek gebruik c # se Lamda uitdrukking sintaksis om dinge netjies te hou:

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

Dit vra my metode en Pogingen tot 5 keer. Op die vyfde poging, is die oorspronklike uitsondering rethrown binnekant van 'n weer probeer uitsondering nie.

Gelisensieer onder: CC-BY-SA met toeskrywing
Nie verbonde aan StackOverflow
scroll top