自定义.NET框架生成的异常消息

本文关键字:异常 消息 NET 框架 自定义 | 更新日期: 2023-09-27 17:58:10

我想知道是否有一种合理的方法可以自定义.NET框架引发的异常消息?下面是我经常在许多不同的场景中编写的一大块代码,以实现向用户提供合理异常消息的效果。

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

正如您所看到的,我本质上是在生成重复的代码,只是为了使用不同的(更好的)消息。

编辑:
我要找的基本上是这样的东西:

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

无论如何,我不认为这样的功能存在,但如果真的存在,我会非常高兴。以前有人解决过这种问题吗?看起来我最终需要某种类型的扩展方法。。。

自定义.NET框架生成的异常消息

除非我在你的问题中遗漏了什么,否则这正是你应该做的。我确信每个异常都包含一个以string message为参数的重载。如果要提供.NET提供的"默认"之外的信息,则需要设置特定的消息。

您似乎以正确的方式开始这样做。然而,我会改变你检查异常的方式:

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

只需从KeyNotFoundException类继承并重写Message属性即可生成更有意义的消息,然后使用具有适当构造函数的异常类。这正是继承的目的,增加价值。即

throw new MetaDataKeyNotFoundException(string metaDataKey);

Exception类已经支持添加与通过使用属性Exception.Data发生错误的特定事件或场景相关联的自定义用户数据。

从该属性的MSDN条目中,重点是我的:

获取键/值对的集合,该集合提供有关异常的其他用户定义信息

我知道您希望覆盖Message属性,但使用Data,只需确保异常处理程序知道如何处理这些附加数据,就可以实现同样的目的。

异常是一个对象。与大多数对象一样,您无法控制创建者如何创建对象,无论创建者是否为.NET Framework。

你会如何告诉.NET Framework在什么情况下创建什么消息?在您发布的案例中,您可能希望KeyNotFoundException上有一条消息,而在不同的情况下需要另一条消息。你如何区分这两种情况?

KeyNotFoundException.SetMessage("此是我的自定义消息!");

没有这样的功能(除了可能干扰内部或资源)。但无论如何,它应该如何工作。您将更改使用异常的每一段代码的消息——对于其中一些代码,您的新消息将毫无意义。

考虑一下Dictionary类的任意使用,甚至一些完全不同的代码,遵循重用现有异常类型的"最佳实践",所有这些代码都会突然使用您的(非常)自定义错误消息。

这是我提出的一个解决方案,但我想指出的是,它更像是一个补丁。它确实有效,但可能不适用于所有应用程序。我甚至想不出一个好名字。

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

所以现在我可以说这样的话,并得到我真正想要的更具描述性的异常消息。

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