65.9K
CodeProject is changing. Read more.
Home

Custom exceptions without constructor tedium (an alternative)

starIconstarIconstarIconstarIconstarIcon

5.00/5 (4 votes)

Oct 1, 2017

CPOL

1 min read

viewsIcon

7201

This is an alternative for "Custom exceptions without constructor tedium"

Introduction

Custom exceptions are tedius, with each one you create demanding five constructor overloads. Recently, and article was published here describing an interesting method for avoiding custom exception overload hell - Custom exceptions without constructor tedium, which utilized generics.

There is no code to download, and there aren't any screen shots in this article. Simply use the code snippets as the basis for your own implementation.

In my recent article series SQLXAgent - Jobs for SQL Express, I created what I think might be a simpler method for doing the same thing, is/can be application (or assembly) specific, and doesn't have the admittedly minor side-effect described in the other article.

The Code

Essentially, the idea is to create an enumerator that contains all ofthe possible exceptions that you want to define, a static class that instantiates and populates a dictionary, and a single custom exception class. The simplicity of it is that to add a new custom exception, you simply add a new enum item, and then a new dictionary item that describes it.

The enumerator looks like this (the actual list of exception codes will be dependent on your own requirements, so I didn't include all of mine here):

public enum SQLXExceptionEnum
{
    // JobThread/JobThreadManager excptions (0 - 99)
    Unknown=999,
    NoCmdLineArgs=1,
    CmdLineArgPkgFilename,
    PkgFileNotFound,
    CmdLineArgStepID,
    CmdLineArgPkgConnString,
    SQLXAgentConfigNotFound,
    SQLXAgentConnStringNotSpecified,
    QueryTextNullEmpty,
    PkgPathNullEmpty,

    // Package exceptions (100-199)
    NotSpecified=100,
    NoInitialCatalog,
    InvalidFileName,
    ImportFileNotFound,

    // ...
}

Next is the static class that maintains the listt of exception codes.

public static class SQLXExceptionCodes
{
    public static Dictionary<int, string> Codes { get; set; }

    static SQLXExceptionCodes()
    {
        SQLXExceptionCodes.Codes = new Dictionary<int,string>();
        Codes.Add((int)SQLXExceptionEnum.Unknown,                         "Unknown error - something bad happened that the application was not anticipating.");
        Codes.Add((int)SQLXExceptionEnum.NoCmdLineArgs,                   "No commandline arguments specified (expecting three).");
        Codes.Add((int)SQLXExceptionEnum.CmdLineArgPkgFilename,           "Commandline argument not specified - package filename");
        Codes.Add((int)SQLXExceptionEnum.PkgFileNotFound,                 "Specified package file not found");
        Codes.Add((int)SQLXExceptionEnum.CmdLineArgStepID,                "Commandline argument not specified - step ID");
        Codes.Add((int)SQLXExceptionEnum.CmdLineArgPkgConnString,         "Commandline argument not specified - package connectionstring");
        Codes.Add((int)SQLXExceptionEnum.SQLXAgentConfigNotFound,         "File not found - SQLXAgent.exe.config");
        Codes.Add((int)SQLXExceptionEnum.SQLXAgentConnStringNotSpecified, "SQLXAgent connection string not found in file SQLXAgent.exe.config");
        Codes.Add((int)SQLXExceptionEnum.QueryTextNullEmpty,              "SQL Step - query text is null or empty");
        Codes.Add((int)SQLXExceptionEnum.PkgPathNullEmpty,                "PKG Step - package path is null or empty");

        Codes.Add((int)SQLXExceptionEnum.NotSpecified,                    "Not specified");
        Codes.Add((int)SQLXExceptionEnum.NoInitialCatalog,                "InitialCatalog (Database) not found in connection string.");
        Codes.Add((int)SQLXExceptionEnum.InvalidFileName,                 "Filename cannot be null/empty");
        Codes.Add((int)SQLXExceptionEnum.ImportFileNotFound,              "Import source file not found");

        // ...
    }
}

And finally, the exception class itself. This is what you would have to do for each of the enums in the list if you wanted to create custom expression for all of them. In the SQLXAgent code, there were over 30 of these exception classes I would have had to write.

public class SQLXAgentException : Exception
{
    public int ReturnValue { get; set; }
    public SQLXAgentException()
    {
        this.ReturnValue = (int)SQLXExceptionEnum.NotSpecified;
    }
    public SQLXAgentException(string message) : base(message)
    {
        this.ReturnValue = (int)SQLXExceptionEnum.NotSpecified;
    }
    public SQLXAgentException(string message, Exception inner) : base(message, inner)
    {
        this.ReturnValue = (int)SQLXExceptionEnum.NotSpecified;
    }
    public SQLXAgentException(SQLXExceptionEnum result):base (SQLXExceptionCodes.Codes[(int)result])
    {
        this.ReturnValue = (int)result;
    }
    public SQLXAgentException(SQLXExceptionEnum result, Exception inner):base (SQLXExceptionCodes.Codes[(int)result], inner)
    {
        this.ReturnValue = (int)result;
    }
}

Usage

Usage is as you might expect it. There's nothing really weird you have to do to throw the exception, and handling it is like any other exception.

try
{
    throw new SQLXAgentException(SQLXExceptionEnum.SQLXAgentConfigNotFound);
}
catch (SQLXAgentException sex)
{
    MessageBox.Show(ex.Message);
}

History

  • 01 Oct 2017 - Initial publication.