34

ある種の独特な状況があります。私は電子メールを送信するためのオープンソースライブラリに取り組んできました。このライブラリでは、呼び出し元のメソッドを取得するための信頼できる方法が必要です。私はその中のオブジェクトをStackTrace分析することによってこれを行いました。StackFrameこれは、最適化がオフになっているデバッグモードプロジェクトでは問題なく機能します。

この問題は、最適化がオンになっているリリースモードに切り替えると発生します。スタックトレースは次のようになります。

> FindActionName at offset 66 in file:line:column <filename unknown>:0:0
> Email at offset 296 in file:line:column <filename unknown>:0:0
> CallingEmailFromRealControllerShouldFindMailersActionName at offset 184
     in file:line:column <filename unknown>:0:0
> _InvokeMethodFast at offset 0 in file:line:column <filename unknown>:0:0
> InvokeMethodFast at offset 152 in file:line:column <filename unknown>:0:0
...

これは、失敗した単体テストから取得されます。このトレースの3行目には、TestEmail他の場所で定義されているというメソッドが表示されているはずですが、JITterがそれをインライン化していると思います。メソッドを仮想化することでインライン化を防ぐことができると読みましたが、これは機能しません。メソッドのインライン化を防ぎ、メソッドがスタックトレースに表示されるようにするための、信頼できる方法を知っている人はいますか?

4

2 に答える 2

42

を使用MethodImplAttributeして指定できますMethodImplOptions.NoInlining

[MethodImpl(MethodImplOptions.NoInlining)]
void YourMethod()
{
    // do something
}

これは、ソースコードに見られるように実際の呼び出しメソッドを取得できることを保証するものではないことに注意してください。メソッドはインライン化されませんが、メソッドの呼び出し元が独自の呼び出し元などにインライン化される可能性があります。

于 2011-03-02T14:57:04.547 に答える
7

でマークされた追加System.Runtime.CompilerServices.CallerMemberNameAttributeのパラメータを使用でき、それは兄弟CallerFilePathCallerLineNumberです。私が正しく理解していれば、インライン化されているものとされていないものに関係なく、正しいメソッド名が得られるはずです。メソッド名しか取得できませんが、クラス名/アセンブリなどを取得するものは何も表示されません。

言うまでもありませんが、念のために言っておきますが、このようなものはロギング/診断以外では使用しないでください。

これを行う適切な方法は、おそらく次のようになります。

  • 必要な情報をパラメータとして渡す
  • Thread.ExecutionContext関数の呼び出し中に必要な情報を一時的に保存します

これはおそらくスコットにとって何の助けにもならないだろうと私は理解していますが、おそらく他の誰かがそれから利益を得ることができます。

于 2013-01-11T15:19:47.077 に答える