Lowering replicate error handling code in C#?

I've never ever been entirely satisfied with the means exception taking care of jobs, there's a whole lot exemptions and also try/catch offers the table (pile taking a break, and so on), yet it appears to damage a great deal of the OO version while doing so.

Anyhow, below's the trouble:

Allow's claim you have some class which covers or consists of networked documents IO procedures (e.g. analysis and also contacting some documents at some certain UNC course someplace). For numerous factors you do not desire those IO procedures to fall short, so if you identify that they fail you retry them and also you maintain retrying them till they do well or you get to a timeout. I currently have a hassle-free RetryTimer class which I can instantiate and also make use of to rest the existing string in between retries and also establish when the timeout duration has actually expired, and so on

. The trouble is that you have a number of IO procedures in numerous approaches of this class, and also you require to cover each of them in try-catch/ retry reasoning.

Below's an instance code fragment:

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, just how do you stay clear of replicating a lot of this code for every single documents IO procedure throughout the class? My remedy was to make use of confidential delegate blocks and also a solitary method in the class which implemented the delegate block passed to it. This permitted me to do points similar to this in various other approaches:

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

I like this rather, yet it leaves a whole lot to be wanted. I would certainly such as to listen to just how other individuals would certainly address this type of trouble.

0
2019-05-06 02:54:40
Source Share
Answers: 3

You can additionally make use of an extra OO strategy:

  • Create a base class that does the error handling and also calls an abstract method to execute the concrete job. (Template Method pattern)
  • Create concrete courses for each and every procedure.

This has the benefit of calling each sort of procedure you execute and also offers you a Command pattern - procedures have actually been stood for as things.

0
2019-05-17 01:32:17
Source

This resembles a superb possibility to look at Aspect Oriented Programming. Below is an excellent write-up on AOP in .NET. The basic suggestion is that you would certainly extract the cross - useful problem (i.e. Retry for x hrs) right into a different class and afterwards you would certainly annotate any kind of approaches that require to change their practices because means. Below's just how it could look (with a wonderful expansion method on Int32)

[RetryFor( 10.Hours() )]
public void DeleteArchive()
{
  //.. code to just delete the archive
}
0
2019-05-10 23:38:56
Source

Just asking yourself, what do you feel your method entrusts to be wanted? You can change the confidential delegate with a. called? delegate, something like

    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
2019-05-08 10:40:12
Source