A.R.
A.R.

Reputation: 15685

Customize .NET framework generated exception messages?

I was wondering if there was a reasonable way to customize messages on exceptions that are thrown by the .NET framework? Below is a chunk of code that I write often, in many different scenarios to achieve the effect of providing reasonable exception messages to my users.

public string GetMetadata(string metaDataKey)
{
  // As you can see, I am doing what the dictionary itself will normally do, but my exception message has some context, and is therefore more descriptive of the actual problem.
  if (!_Metadata.ContainsKey(metaDataKey))
  {
    throw new KeyNotFoundException(string.Format("There is no metadata that contains the key '{0}'!", metaDataKey));
  }

  // This will throw a 'KeyNotFoundException' in normal cases, which I want, but the message "The key is not present in the dictionary" is not very informative.  This is the exception who's message I wish to alter.
  string val = _Metadata[metaDataKey].TrimEnd();
  return val;
}

As you can see, I am essentially producing duplicate code just to use a different (better) message.

Edit:
What I am looking for, essentially is something like this:

KeyNotFoundException.SetMessage("this is my custom message!")
{
// OK, now this will send off the message I want when the exception appears!
// Now I can avoid all of that silly boilerplate!
string val = _Metadata[metaDataKey].TrimEnd();
}

At any rate, i don't think that such a feature exists, but if it did I would be very pleased indeed. Has anyone tackled this type of problem before? It's looking like I am going to wind up needed some type of extension method in the end...

Upvotes: 2

Views: 524

Answers (7)

A.R.
A.R.

Reputation: 15685

Here is a solution that I came up with, but I would like to note that it is more of a patch than anything. It does work, but probably isn't suitable for all applications. I couldn't even think of a good name for it either.

  public class ContextDictionary<TKey, TValue> : Dictionary<TKey, TValue>
  {
    public TValue this[TKey key, string context]
    {
      get
      {
        if (!this.ContainsKey(key))
        {
          throw new KeyNotFoundException(string.Format("There is no {0} that contains the key '{1}'!", context, key));
        }
        return this[key];
      }
      set { this[key] = value; }
    }
  }

So now I can say something like this, and get the more descriptive exception message that I really want.

var _MetaData = new ContextDictionary<string,string>();
string val = _Metadata[metaDataKey, "metadata"].TrimEnd();

Upvotes: 0

Christian.K
Christian.K

Reputation: 49230

KeyNotFoundException.SetMessage("this is my custom message!");

There is no such feature (apart from messing with internals or resources maybe). But how should it work anyway. You would be changing the message for every piece of code that uses the exception - to some of which your new message would make no sense at all.

Consider some arbitrary use of the Dictionary class, or even some totally different code, that follows the "best practice" of reusing existing exception types, all of them would suddenly use your (very much) custom error message.

Upvotes: 0

Jo&#227;o Angelo
Jo&#227;o Angelo

Reputation: 57658

The Exception class already supports adding custom user data associated to a specific occurrence or scenario in which the error occurred through the use of the property Exception.Data.

From MSDN entry for that property, emphasis is mine:

Gets a collection of key/value pairs that provide additional user-defined information about the exception.

I know that you were looking to override the Message property, but using Data you can achieve the same by just making sure that the exception handler knows how to deal with this additional data.

Upvotes: 1

Chris Walsh
Chris Walsh

Reputation: 1903

You seem to be doing this the right way to begin with. I would however change the way you check for exceptions:

public string GetMetadata(string metaDataKey)
{
    try
    {
        string val = _Metadata[metaDataKey].TrimEnd();
        return val;
    }
    catch (KeyNotFoundException ex)
    {
        // or your own custom MetaDataNotFoundException or some such, ie:
        // throw new MetaDataNotFoundException(metaDatakey);
        throw new KeyNotFoundException(string.Format("There is no metadata that contains the key '{0}'!", metaDataKey));
    }
}

Upvotes: 3

Teoman Soygul
Teoman Soygul

Reputation: 25732

Just inherit from the KeyNotFoundException class and override the Message property to generate a more meaningful message and then use your own exception class with a proper constructor. This is exactly what inheritance was meant for, adding value. i.e.

throw new MetaDataKeyNotFoundException(string metaDataKey);

Upvotes: 2

John Saunders
John Saunders

Reputation: 161773

An exception is an object. As with most objects, you can't control how the creator creates the object, whether or not the creator is the .NET Framework.

How would you even tell the .NET Framework what message to create under which circumstances? You would want one message on a KeyNotFoundException in the case you posted, and another message in a different circumstance. How would you distinguish the two situations?

Upvotes: 0

AllenG
AllenG

Reputation: 8190

Unless I'm missing something in your question, this is exactly what you're supposed to be doing. I'm pretty sure every exception includes an overload that takes string message as a parameter. If you want to provide information above and beyond the "default" provided by .NET, you need to set the specific message.

Upvotes: 3

Related Questions