C # (не ASP / MVC / WinForms) - перехватить все исключения в классе

Некоторая справочная информация

Я программирую в системе, которая использует проприетарный язык программирования, с возможностью использования классов .Net со специальными атрибутами в частном коде.

К сожалению, система плохо обрабатывает необработанные исключения, возникающие из кода .Net, если на самом деле нет; система вылетает без объяснения причин. Это раздражает, потому что мы часто хотим обрабатывать исключения в проприетарной системе , а не в коде .Net. Решение, предлагаемое поставщиком системы, состоит в том, чтобы переупаковать исключение в специальный объект, который система обрабатывает .

Наш код .Net написан в виде фасада, и проблема заключается в том, чтобы убедитесь, что каждое исключение, которое возникает из кода .Net, обрабатывается, каждый метод в фасаде должен включать блок try / catch, который переупаковывает любые исключения, которые могут возникнуть.

Вопрос

Я прочитал здесь много веток, описывающих похожие сценарии, большинство из которых связаны с WinForms или сетью. Поскольку наш код не является ни тем, ни другим, вопрос в том, есть ли способ перехватить все исключения в классе, чтобы мы могли переупаковать его и повторно выбросить их модифицированную версию?

Очевидно, интерфейс между DLL-библиотеками .Net, содержащими классы и собственный язык полностью вне нашего контроля.

Edit

Я попробовал метод currentDomain.UnhandledException , предложенный @VMAtm, к сожалению, безрезультатно. Обработчик событий не сработал, и родительская система перехватила исключение, а затем вела себя как обычно. Это снова привело меня к Google, и я нашел этот параграф здесь :

Первое, что нужно понять, это то, что событие UnhandledException не является «обработчиком» необработанного исключения. Регистрация для события, вопреки тому, что говорится в документации :-(, не приводит к обработке необработанных исключений. (С тех пор они не будут необработанными, но я уже остановлюсь на круговых рассуждениях ...) UnhandledException событие просто уведомляет вас о том, что исключение осталось необработанным, на случай, если вы хотите попытаться сохранить состояние до того, как ваш поток или приложение умрет.

Джонатан Келджо, Менеджер по исключениям CLR

Это было очень плохо, мне понравилась идея иметь "глобальный" блок try / catch. Я думаю, это означает, что мне не удалось скрыть исключение от родительской системы. Поскольку я не знаю, как это реализовано в этой системе (и, честно говоря, , Я не знаю, в первую очередь, как бы я реализовал это сам) Я нахожусь на очень тонком льду со своими предположениями, поэтому, если кто-то может исправить меня каким-либо образом, пожалуйста, продолжайте! ,ошибка, которую я получаю в родительской системе, - Исключение было выброшено целью вызова. , что, насколько мне известно, является сообщением из внешнего исключения .Net. Если можно что-нибудь из этого прочесть, я не знаю.

Я тоже попробую Castle Dynamic Proxy, предложенный @jlew, но он выглядел намного сложнее, чем две строки AppDomain, и напугал меня совсем немного :)

Решение

Если у вас такая же проблема, как и у меня, вы должны сначала попробовать метод currentDomain.UnhandledException , предложенный @VMAtm, потому что это из-за моего родителя система была особенно анальной, она не работала.

Я заставил ее работать, используя установку Castle DynamicProxy. Настроить было действительно очень просто. Моим тестовым примером был класс фасада, инкапсулирующий класс XmlAttribute. Первое, что мне нужно было сделать, это написать прокси-класс:

public class AttribInterceptor : IInterceptor
{
    public void Intercept(IInvocation invocation)
    {
        try
        {
            invocation.Proceed();
        }
        catch (Exception e)
        {
            // Custom exception repackaging here
        }
    }
}

Затем я должен был проинструктировать фасадный объект на самом деле использовать прокси. Я сохранил свое старое бэкэнд-поле, но добавил в c'tor следующее:

public class CapXmlAttribute : CapPmlNetObject
{
    private XmlAttributeBackend _xmlAttribute;

    public CapXmlAttribute()
    {
        var generator = new ProxyGenerator();
        _xmlAttribute = (XmlAttributeBackend) generator.CreateClassProxy(
            typeof (XmlAttributeBackend), new AttribInterceptor());
    }
}

Последним шагом была установка всех методов в бэкэнде, который доступен фасаду, как виртуальный . Для меня это не было проблемой, но могло стать препятствием для других.

DynamicProxy действительно не так хорошо документировано, но я многому научился из учебника Кшиштофа Кёмика и Гамильтона. Проект кода Вериссимо .

20
задан joneberg 8 July 2011 в 06:35
поделиться