查找重新抛出的未通过 RegEx 设置内部异常的 catch 语句

本文关键字:内部 设置 异常 RegEx catch 语句 新抛出 查找 | 更新日期: 2023-09-27 18:32:52

我正在尝试找到所有重新抛出异常的代码,其中抛出的新异常不包含原始异常作为内部异常。下面是一个示例:

            catch(DBApplicationException dbEx) 
        {
            BaseApplicationException bEx = new BaseApplicationException(dbEx.Message, dbEx);
            bEx.MethodName = System.Reflection.Assembly.GetExecutingAssembly().FullName + "::" + System.Reflection.MethodBase.GetCurrentMethod().Name.ToString();
            bEx.Severity = ExceptionSeverityLevel;
            PublishingManager.Publish(bEx,"");
            throw bEx;
        }
        catch(Exception e) 
        {
            BaseApplicationException bEx = new BaseApplicationException(e.Message);
            bEx.MethodName = System.Reflection.Assembly.GetExecutingAssembly().FullName + "::" + System.Reflection.MethodBase.GetCurrentMethod().Name.ToString();
            bEx.Severity = ExceptionSeverityLevel;
            PublishingManager.Publish(bEx,"");
            throw bEx;
        }

第一个 catch(catch (DBApplicationException dbEx( 被重新抛出为 BaseApplicationException,但如您所见,它将消息设置为 dbEx.Message,然后将 InnerException 指定为 dbEx,但第二个 catch 段在没有 InnerException 的情况下重新抛出,它只包含 e.Message。

因此,对于我的正则表达式模式,我只想找到不包含内部异常的整个 catch 块,现在,我使用的模式将这两个 catch 块一起返回。

这是我的正则表达式模式:

catch((.|'n|'r)*){((.|'n|'r)*)Exception'(((?!,).)+');((.|'n|'r)*)}

这是我测试此方案的方法块:

public static DataSet SearchUserSessions(string username, string first, string last, string startDate, string endDate) 
    {
        DataSet ds = null;
        try 
        {
            SqlParameter [] arParms = new SqlParameter[]
            {
                new SqlParameter("@UserName", username),
                new SqlParameter("@FirstName", first),
                new SqlParameter("@LastName", last),
                new SqlParameter("@SessionStart", startDate),
                new SqlParameter("@SessionEnd", endDate)
            };
            DB db = new DB();
            ds = db.ExecuteDataset(SecurityConfig.ConnectionString, CommandType.StoredProcedure, 
                SPSearchUserSessions, (DB.Provider)SecurityConfig.ConnectionProviderType, 
                arParms); 
        }
        catch(DBApplicationException dbEx) 
        {
            BaseApplicationException bEx = new BaseApplicationException(dbEx.Message, dbEx);
            bEx.MethodName = System.Reflection.Assembly.GetExecutingAssembly().FullName + "::" + System.Reflection.MethodBase.GetCurrentMethod().Name.ToString();
            bEx.Severity = ExceptionSeverityLevel;
            PublishingManager.Publish(bEx,"");
            throw bEx;
        }
        catch(Exception e) 
        {
            BaseApplicationException bEx = new BaseApplicationException(e.Message);
            bEx.MethodName = System.Reflection.Assembly.GetExecutingAssembly().FullName + "::" + System.Reflection.MethodBase.GetCurrentMethod().Name.ToString();
            bEx.Severity = ExceptionSeverityLevel;
            PublishingManager.Publish(bEx,"");
            throw bEx;
        }
        return ds;
    }

查找重新抛出的未通过 RegEx 设置内部异常的 catch 语句

这与您的示例相反:

catch'((([^)]|'n|'r)*)')'s*{(([^}]|'n|'r)*?)Exception'(([^,](?!'n))+?');(([^}]|'n|'r)*)}

但我同意这不是解决此问题的可维护方法 - 除非这是一次性检查。

如果我理解你想做什么,这将是非常困难的。主要原因是您尝试返回整个catch块,这意味着您必须(至少部分(分析 C#。这是因为 catch 块由{...}结构表示,并且可以在其中嵌套其他{...}块:

catch (Exception e)
{
    if (condition)
    {
        doSomething();
    }    
}

对于标识 catch 块末尾的正则表达式,它必须平衡 { 和 } 符号以确保它们匹配。这在具有平衡组的 .NET 正则表达式中是可能的,但它将比您讨价还价的要复杂得多。

我还注意到您的正则表达式非常宽松。你用(.|'n|'r)你并不真正想匹配每个字符,而且你所有的量词都是贪婪的。这点在这里...

{((.|'n|'r)*)Exception'(((?!,).)+');((.|'n|'r)*)}

。实际上会匹配单词的第一个实例catch到文件中最后一个}之间的所有内容,只要它在任何地方找到类似Exception(blah)的东西。事实上,blah可以是没有逗号的任何东西,甚至是另一个陈述。 理论上Exception(); DoStuff();会匹配它!

IMO 的最佳选择是在BaseApplicationException类上使用 Visual Studio 的查找使用实例功能。您可以找到整个类的所有用法,然后也许将其与BaseApplicationException.InnerException的所有用法进行比较。如果您必须使用正则表达式,这至少应该获得 99% 的 catch 块,没有嵌套的 {...} 块(为清楚起见进行了扩展(:

^'s*                          #Beginning of a line, possibly followed by whitespace
catch['s'n]*                  #catch, possibly followed by whitespace
'('w*Exception's+'w+')['s'n]* #Some type of Exception declaration, possibly followed by whitespace
'{                            #An opening brace
(:?(?!'.InnerException)[^}])* #Anything except a closing brace, without the term `.InnerException` appearing anywhere
'}                            #The closing brace of the block

正如我上面提到的,这将阻塞嵌套的{...}块。你可以用平衡组来解决这个问题,但我想保持简单。

听起来非常

困难且难以维护。你能在你的项目中强制BaseApplicationException作为一个"包装器"异常抛出吗?然后,您可以删除仅接受字符串的构造函数,并在剩余的一个构造函数中测试 null 的内部异常。