2

Microsoft Enterprise Library の一部として Unity (v2.0) を使用しているアプリケーションを使用しています。メソッドの先頭に属性を追加できるように設定されており、メソッドが実行される前に何らかの処理 (トレース/ロギング/キャッシュなど) が行われます。以下のサンプルコード:

static void Main(string[] args)
{
    IUnityContainer myContainer = new UnityContainer()
        .AddNewExtension<Interception>()
        .RegisterType<IFoo, Foo>(
            new Interceptor<InterfaceInterceptor>(),
            new InterceptionBehavior<PolicyInjectionBehavior>()
        );
    IFoo myFoo = myContainer.Resolve<IFoo>();

    myFoo.fooMethodCall();
}

public class TraceAttribute : HandlerAttribute
{
    public override ICallHandler CreateHandler(IUnityContainer container)
    {
        return new TraceCallHandler();
    }
}

public class TraceCallHandler : ICallHandler
{
    public int Order { get; set; }

    public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext)
    {
        IMethodReturn methodReturn;
        //Do tracing/chaching/other funky stuff
        methodReturn = getNext()(input, getNext);       
        return methodReturn;
    }
}

public interface IFoo
{
    int fooMethodCall();
}

public class Foo : IFoo
{
    [Trace]
    public int fooMethodCall()
    {
        return 0;
    }
}

さて、これが機能する方法に関して私が抱えている 2 つの厄介な問題と、1 つのかなり深刻な問題があります。最初の煩わしさは、生成されるスタック トレースのサイズですここを参照。5 レベルの深さの関数をデバッグしようとすると、ナビゲートするのが非常に難しい厄介なスタック トレースが発生します。

2 番目の煩わしさは、VS2010 を使用してデバッグする場合、ステップインできないように見えることfooMethodCallです。ステップ インしようとすると、メソッド呼び出しをステップ オーバーしようとした場合と同じ動作になります。

私が抱えている実際の問題は、エラー処理にあります。次のように変更fooMethodCallしたとします。

public int fooMethodCall()
{
    throw new Exception();
}

次のように呼び出します。

try 
{
    myFoo.fooMethodCall();
} 
catch Exception(e)
{
    //do something with the exception
}

e.StackTrace を調べると、ほとんど役に立ちません。

at DynamicModule.ns.Wrapped_IFoo_dd88617b4f734f1987dc0099d195ca52.fooMethodCall()
at ConsoleApplication1.Program.Main(String[] args) 
in C:\Projects\ConsoleApplication1\Program.cs:line 152

これでわかるのは、fooMethodCall が失敗したということだけです。最初に失敗したか、5 レベル下にネストされたメソッドで失敗した可能性があります。

これについていくつか質問があります。このコードは正しく見えますか? もしそうなら、私がリストした煩わしさ/問題は、メソッド呼び出しをインターセプトするときに避けられないものですか? 私が達成しようとしていることを行うためのより良い方法はありますか?

4

2 に答える 2

2

ここで同じ質問をしました: Unity のコール サイトでインターセプトされたメソッドの完全なスタック トレースが提供され、次のスレッドが提供されました: In C#, how can I rethrow InnerException without loss stack trace?

最終的に、2 番目のリンクの手法を使用してトレースを保持するパイプラインの最初のインターセプターを追加することになりました。これは全体的に少しブードゥーで悪い慣習であることは認めますが、完全なスタック トレースを取得することに関してはあまり問題になりませんでした。

于 2012-08-30T22:20:35.720 に答える
2

戻り値の例外を新しい例外に設定するだけです。例えば:

public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext)
{
    IMethodReturn r = getNext()(input, getNext);
    if (r.Exception != null) r.Exception = new Exception("NameOfInterceptor", r.Exception);
    return r;
}
于 2014-03-31T16:39:54.657 に答える