2016-01-26 3 views
2

У меня есть класс низкого уровня, который импортирует внешний C++ функции, такие как:Массовое преобразование кодов ошибок в исключения

public static class LowLevel 
{ 
    [DllImport("DLLName.dll", CallingConvention = CallingConvention.Cdecl)] 
    public static extern int DoStuff([MarshalAs(UnmanagedType.LPStr)] string parameter); 

    [DllImport("DLLName.dll", CallingConvention = CallingConvention.Cdecl)] 
    public static extern int DoStuff2(int parameter); 
    ... 
} 

Теперь, есть много способов, и все они возвращают код ошибки. Я хотел бы, чтобы инкапсулировать и преобразовать эти коды ошибок исключений т.е .:

public static void DoStuff(string parameter) 
{ 
     int error = LowLevel.DoStuff(parameter); 
     if (error != 0) 
      throw new MyException(error); 
} 

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

+0

Это сценарии для оболочки или Perl. Это довольно распространенный подход с бесплатным программным обеспечением в Linux. Исходный код обычно имеет файл метаданных какого-либо типа в формате XML, YAML или в формате homebrew. В качестве части построения кода запускается оболочка или скрипт Perl, а robo - генерирует объявления или структуры данных, которые затем скомпилируются. К сожалению, платформа Microsoft Windows не столь надежна, когда речь заходит о средствах разработки на основе скриптов и предпочтениям типа pointy-clicky-GUI. –

+0

@SamVarshavchik: Это вопиющий вздор.Интеграция пользовательского сценария в процесс сборки, который генерирует некоторый код перед его компиляцией, тривиальна, и поддержка существует даже в инструментах графического интерфейса, таких как Visual Studio. Однако, если это лучшее решение проблемы, это еще один вопрос. – Joey

ответ

2

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

Ваша обложка выглядит нормально (отсутствует документация, я думаю). Одна вещь, которую я, вероятно, сделаю, будет заключаться в использовании разумных исключений в зависимости от того, что означает код отказа, например. бросьте FileNotFoundException вместо MyException(2). Тем не менее это исключает практически любой автоматизированный подход.

Что касается автоматизации этого метода, то ReSharper позволяет определять быстрые исправления на основе поиска по шаблону. Это может помочь, по крайней мере, автоматически генерировать некоторые из шаблонов.

Другим вариантом будет Roslyn, каркас компилятора с открытым исходным кодом Microsoft с открытым исходным кодом. Visual Studio 2015 позволяет писать быстрые исправления с API-интерфейсом Roslyn, если вы хотите что-то интегрированное в IDE (похожее на то, что ReSharper обеспечивает тем, что я упомянул выше). Но вы также можете использовать библиотеки, чтобы просто написать небольшой инструмент, который сгенерировал соответствующий код клея.

Другие варианты генерации кода: T4 templates, который, по крайней мере, Visual Studio знает, как автоматически восстанавливать при необходимости (хотя это не будет сделано в файлах сборки). Я также использовал PowerShell в прошлом для генерации исходного кода. В одном случае, глядя на скомпилированную сборку и генерируя код на основе типов и методов в определенном пространстве имен (перечисляя это через отражение), который может работать здесь и с вашим классом LowLevel.


Автоматически сгенерированный код является немного сложной штукой. Если вам нужно внести изменения в сгенерированный код, то ваши варианты меньше или вам необходимо творчески использовать частичные классы или ветви и слияния в вашей системе управления версиями, чтобы избежать сглаживания написанного вручную кода с помощью регенерированного кода.

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

+0

Библиотека C++ является, по сути, HW-драйвером, поэтому все ненулевые коды являются неожиданными результатами, за исключением 1-2, которые могут возникать ежедневно, но обработка их по отдельности не будет слишком затруднять управление потоком. Вы воспитываете хорошую точку с FileNotFoundException, я думаю, что я сделаю это вручную, так как у меня нет Resharper, и другие формы автоматизации, вероятно, занимают одинаковое время для настройки. Кроме того, я могу удвоить и избавиться от некоторого сортировки таким образом (строковые сборщики для строк, ints для перечислений и т. Д.). – Paprik

+0

Это, вероятно, сводится к тому, сколько методов существует, сколько времени требуется, чтобы делать вручную, насколько вам комфортно с различными вариантами написания скриптов и сколько времени потребуется для этого. На работе я использовал генерацию кода (используя PowerShell и отражение) для автоматического внедрения различных реализаций посетителя над деревом синтаксиса. Когда мы добавляем классы или свойства, мы можем просто восстановить посетителей. В этом случае генератор был около одного дня работы, и в качестве выгоды мы не можем забыть скопировать некоторые свойства и т. Д. Я использовал T4 в том же проекте для создания нескольких тестов. – Joey

Смежные вопросы