Reputation: 15685
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
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
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
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
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
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
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
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