Полная трассировка стека для перехваченных методов на месте вызова в Unity

Мы рассматриваем возможность использования Unity для обработки методов службы ведения журналов с перехватом. Однако одна проблема заключается в том, что полная трассировка стека недоступна на месте вызова; он доступен только в вызове перехватчика.

Вот пример настройки:

public interface IExceptionService
{
    void ThrowEx();
}

public class ExceptionService : IExceptionService
{
    public void ThrowEx()
    {
        throw new NotImplementedException();
    }
}

public class DummyInterceptor : IInterceptionBehavior
{
    public IEnumerable<Type> GetRequiredInterfaces()
    {
        return Type.EmptyTypes;
    }

    public IMethodReturn Invoke(IMethodInvocation input, GetNextInterceptionBehaviorDelegate getNext)
    {
        IMethodReturn ret = getNext()(input, getNext);
        if (ret.Exception != null)
            Console.WriteLine("Interceptor: " + ret.Exception.StackTrace + "\r\n");
        return ret;
    }

    public bool WillExecute
    {
        get { return true; }
    }
}

class Program
{
    static void Main(string[] args)
    {
        IUnityContainer container = new UnityContainer();
        container.AddNewExtension<Interception>();

        container.RegisterType<IExceptionService, ExceptionService>(
            new Interceptor<InterfaceInterceptor>(),
            new InterceptionBehavior<DummyInterceptor>());

        try
        {
            container.Resolve<IExceptionService>().ThrowEx();
        }
        catch (Exception e)
        {
            Console.WriteLine("Call Site: " + e.StackTrace);
        }

    }
}

Вот вывод консоли при запуске этой программы:

Interceptor:
at ConsoleDemo.ExceptionService.ThrowEx() in    C:\code\ServiceDemo\ConsoleDemo\Program.cs:line 25
at DynamicModule.ns.Wrapped_IExceptionService_248fe3264f81461f96d34670a0a7d45d.<ThrowEx_DelegateImplementation>__0(IMethodInvocation inputs, GetNextInterceptionBehaviorDelegate getNext)

Call Site:
at DynamicModule.ns.Wrapped_IExceptionService_248fe3264f81461f96d34670a0a7d45d.ThrowEx()
at ConsoleDemo.Program.Main(String[] args) in C:\code\ServiceDemo\ConsoleDemo\Program.cs:line 63

Трассировка стека в перехватчике в порядке, и ее будет достаточно для ведения журнала на уровне службы. Однако мы теряем все, кроме перехвата прокси-вызова в месте вызова;

Я могу обернуть исключение в перехватчике в ServiceException или что-то в этом роде, и это сохранит стек вызовов во внутреннем исключении, но это приведет к неудобным сценариям ведения журнала и проверки отладки (хотя и менее неудобно, чем полная потеря трассировки).

Я также заметил, что мы получаем более или менее то, что хотим, когда используем TransparentProxyInterceptor, но он считается более медленным, чем InterfaceInterception, и вызывает тревожные сигналы для некоторых групп.

Есть ли более чистый способ получить полную трассировку стека с перехватом Unity на месте вызова на прокси?


person Nick    schedule 01.08.2012    source источник


Ответы (1)


В .NET 4.5 будет ExceptionDispatchInfo для этой цели.

Для всех других версий вы можете увидеть этот вопрос:
Как в C# повторно сгенерировать InnerException без потери трассировки стека?

person Andrey Shchekin    schedule 02.08.2012
comment
@Nick, можешь подробнее рассказать, что ты в итоге сделал? - person Robert Ivanc; 21.03.2014
comment
У меня больше нет доступа к этому коду, но он передал ret.Exception в моем исходном вопросе примерным методам из ссылки SO в принятом ответе (фактически PreserveStackTrace(ret.Exception) из здесь). Я также попробовал подход, основанный на отражении, позже в строке комментария, который работал на .NET 4.0. Если бы мы перешли на .NET 4.5, когда я еще работал над ним, я бы вместо этого рассмотрел возможность использования ExceptionDispatchInfo. - person Nick; 22.03.2014
comment
В моем случае использование ExceptionDispatchInfo работает в режиме отладки, но не в режиме выпуска. Любая причина для этого? - person rlesias; 28.01.2019