0

我试图找到我们所有重新抛出异常的代码,其中抛出的新异常不包含作为内部异常的原始异常。这是一个例子:

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

3 回答 3

2

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

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

为了使正则表达式识别 catch 块的结尾,它必须平衡 { 和 } 符号以确保它们匹配。这在带有平衡组的 .NET 正则表达式中是可能的,但它会比您想象的要复杂得多。

我还注意到您的正则表达式非常宽松。你已经使用(.|\n|\r)了你不想匹配每个字符的地方,并且你所有的量词都是greedy。这里的一点...

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

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

IMO 最好的选择是在课堂上使用 Visual Studio 的Find Usages功能BaseApplicationException。您可以找到整个类的所有用法,然后将其与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

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

于 2012-05-02T15:57:52.670 回答
2

这不利于您的示例:

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

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

于 2012-05-02T15:41:47.737 回答
0

听起来非常困难且难以维护。您可以在您的项目中强制 BaseApplicationException作为“包装器”异常抛出吗?然后,您可以删除只接受一个字符串的构造函数,并在剩下的一个构造函数中测试内部异常是否为 null。

于 2012-05-02T15:33:50.750 回答