3

Unity を AoP フレームワーク、特に VirtualMethodInterceptor + CallHandler として使用しているときに気付きました。

取得したスタック トレースには、元のコードは含まれていません。代わりに、xxx_wrapper_yyyy 型のクラスがあります。これは、元のクラスから動的に継承されるクラスであると想定しています。当然のことながら、動的クラスのソース コードはこれまでに作成されていないため、元のコードでエラーが発生した行番号は報告されていません。

どうすればこれを変更できますか? 例外がスローされたスタック トレースと行番号が必要です。

参考までに、コール ハンドラは意図したとおりに機能しています。例外が発生した元の仮想メソッドの行番号が欠落しているだけです。また、呼び出しハンドラには、例外を飲み込んだり処理したりする行は含まれていません。

4

2 に答える 2

2

このコードの使用

[TestMethod]
public void Should_Wrap_Exception_ThrownByTarget()
{
  var container = new UnityContainer();
  container.RegisterType<Target>(
    new Interceptor<VirtualMethodInterceptor>(), 
    new InterceptionBehavior<PolicyInjectionBehavior>());
  container.AddNewExtension<Interception>();
  var config = container.Configure<Interception>();
  config.AddPolicy("1").AddCallHandler<ExceptionHandler>().AddMatchingRule<AlwaysMatches>();
  var target = container.Resolve<Target>();
  target.AlwaysThrows("foo");
}
public class AlwaysMatches : IMatchingRule
{
  public bool Matches(MethodBase member)
  {
    return true;
  }
}
public class ExceptionHandler : ICallHandler
{
  public int Order { get; set; }
  public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext)
  {
    IMethodReturn r = getNext()(input, getNext);
    if (r.Exception != null)
    {
      throw new InvalidOperationException("CallHandler", r.Exception);
    }
    return r;
  }
}
public class Target
{
  public virtual string AlwaysThrows(string foo)
  {
    throw new Exception("Boom!");
  }
}

このようなスタックトレースを取得します

   at UnityExceptionAspect.Target.AlwaysThrows(String foo) in C:\VisualStudio\Evaluation\UnityExceptionAspect\Target.cs:line 9
   at DynamicModule.ns.Wrapped_Target_c49f840ef38c41d7b4d5956223e95f73.<AlwaysThrows_DelegateImplementation>__0(IMethodInvocation inputs, GetNextInterceptionBehaviorDelegate getNext)

整形が下手ですみません…

生成された型に関する暗号化された情報によって難読化されていますが、例外の元のソースが確実に含まれています。

于 2012-10-03T11:22:33.427 に答える
0

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

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:38:47.147 に答える