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として指定しますが、2番目のcatchセグメントはInnerExceptionなしで再スローされます。 、e.Messageのみが含まれます。

したがって、正規表現パターンの場合、内部例外を含まないcatchブロック全体を検索するだけです。現在、使用しているパターンは、これら2つの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\((([^)]|\n|\r)*)\)\s*{(([^}]|\n|\r)*?)Exception\(([^,](?!\n))+?\);(([^}]|\n|\r)*)}

しかし、それが1回限りのチェックでない限り、これに取り組むための維持可能な方法ではないことに同意します。

于 2012-05-02T15:41:47.737 に答える
2

あなたがやろうとしていることを私が理解していれば、これは非常に難しいでしょう。主な理由は、ブロック全体を返そうとしていることです。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は、クラスでVisualStudioの使用状況の検索機能を使用することです。BaseApplicationExceptionクラス全体のすべての使用法を見つけて、それをのすべての使用法と比較することができますBaseApplicationException.InnerException。正規表現を使用する必要がある場合、ネストされたブロックなしで少なくとも99%のキャッチブロックを取得する必要があります{...}(わかりやすくするために拡張されています)。

^\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 に答える
0

非常に難しく、維持するのが難しいように聞こえます。BaseApplicationExceptionが「ラッパー」例外としてのみスローされるようにプロジェクトで強制できますか?次に、文字列のみを受け取るコンストラクターを削除し、残りの1つのコンストラクターでnullの内部例外をテストできます。

于 2012-05-02T15:33:50.750 に答える