ADN Open CIS
Сообщество программистов Autodesk в СНГ

08/08/2014

Работа с кодом надстройки для различных версий Revit

Как правило, с выпуском новой версии Revit меняется и его API – появляются новые методы, исчезают старые. Надстройка же зачастую должна работать как в новой версии, так и в старой. Разработчик должен при этом должен как-то обслуживать код для различных версий Revit.

Данная проблема возникает естественно не только с Revit, но по сути с любым другим продуктом, поэтому описанный ниже подход годится не только для Revit.

Итак, что же приходится делать разработчику, когда вышла новая версия продукта:

1)      Поменять ссылки на сборки Revit, используемые в проекте, с одной версии на другую

2)      Изменить вызов устаревших методов новыми.

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

Для решения подобных проблем необходимо в проекте создать несколько различных конфигураций построения сборок. Думаю, все видели в Visual Studio раскрывающийся список конфигураций, содержащий Debug и Release:

 

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

С помощью конфигурации настраиваются параметры построения сборки. Например, в режиме Debug, в конечную сборку файла dll или exe включается дополнительная информация, помогающая программисту в отладке, в режиме Release такой информации нет. Нам же, в данном случае, интересно то, что для различных конфигураций можно задать различные константы, которыми можно задавать условия компиляции.

По умолчанию существуют 2 встроенные константы – DEBUG и TRACE. В конфигурации Debug, как не сложно догадаться, определена константа DEBUG.

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

А достаточно написать так:

Код - C#: [Выделить]
  1.             FilteredElementCollector col
  2.               = new FilteredElementCollector(doc)
  3.                 .WhereElementIsNotElementType()
  4.                 .OfCategory(BuiltInCategory.INVALID)
  5.                 .OfClass(typeof(Wall));
  6.            
  7. #if DEBUG
  8.             // Этот код выполнится, а точнее даже сказать скомпилируется
  9.             // только если определена константа DEBUG
  10.             TaskDialog.Show("Вспомогательная инфомация", string.Format("Кол-во элементов: {0}", col.Count()));
  11. #endif

Если же константа не определена (конфигурация Release), то код, заключенный между #if … #endif попросту игнорируется при сборке проекта.

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

Итак, рассмотрим пример, когда наша надстройка должна поддерживать 3 версии Revit – 2013, 2014, 2015.

Создаем 3 дополнительные конфигурации: Revit 2013, Revit 2014 и Revit 2015

Примечание. По идее надо создать 6 конфигураций: Debug и Release для всех 3 версий. Однако, для простоты рассмотрим только 3.

Для создания новой конфигурации, выберите Configuration Manager… в списке, что на скриншоте выше. Либо зайдите Build -> Configuration Manager.

 

В следующем окне в списке активных конфигураций решения (Active Configuration Solution) выберите <New…>

 

Введите имя – Revit 2013. Копировать настройки из конфигурации Debug поставьте галочку о необходимости создания конфигурации проекта с таким же именем:

 

Нажмите OK и создайте таким же образом 2 остальные конфигурации. Конфигурация Debug нам по сути теперь не нужна, поэтому можно ее удалить.

В итоге мы создали 3 различные конфигурации, под различные версии Revit.

Следующий шаг - установка констант для каждой конфигурации.

Для установки констант, зайдите в свойства проекта (Project -> Properties) и выберите вкладку Build.

Выберите конфигурацию и для каждой конфигурации задайте соответствующую константу: REVIT2013 для Revit 2013 и т.д.

 

Константы успешно заданы, можно уже начинать ими пользоваться.

Простой пример. Revit 2013  и 2014 для того чтобы получить параметр элемента по имени, нужно воспользоваться методом get_Parameter(). Однако, в 2015 этот параметр помечен как устаревший и необходимо использовать LookupParameter().

Для этого в коде пишем, например, так:

Код - C#: [Выделить]
  1.             foreach (Element e in col)
  2.             {
  3.                 var heightParam =
  4. #if REVIT2013
  5.                     e.get_Parameter("Высота");
  6. #elif REVIT2014
  7.                     e.get_Parameter("Высота");
  8. #elif REVIT2015
  9.                     e.LookupParameter("Высота");
  10. #endif
  11.             }

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

Но мы решили таким образом только одну проблему. Вторая проблема заключается в изменении подключенных сборок. Ведь если мы подключили сборки от Revit 2013, а в конфигурации выбрали Revit 2015, то проект просто не скомпилируется, так как метода LookupParameter в Revit 2013 не существует.

К сожалению, в интерфейсе Visual Studio это нам сделать не удастся. Это плохая новость. Хорошая заключается в том, что это все же можно сделать, но руками в текстовом редакторе.

Итак, для того чтобы менять ссылки на сборки различных версий Revit, откройте файл проекта .cproj в текстовом редакторе.

Найдите строки, где идет подключение Revit’овских сборок. Это должно выглядеть примерно так:

Код - XML: [Выделить]
  1.     <Reference Include="RevitAPI">
  2.       <HintPath>C:\Program Files\Autodesk\Revit Architecture 2014\RevitAPI.dll</HintPath>
  3.       <Private>False</Private>
  4.     </Reference>
  5.     <Reference Include="RevitAPIUI">
  6.       <HintPath>C:\Program Files\Autodesk\Revit Architecture 2014\RevitAPIUI.dll</HintPath>
  7.       <Private>False</Private>
  8.     </Reference>

Нам нужно подключать сборки по различному пути, в зависимости от версии.

Подправьте файл проекта, удалите строки, что я указал выше и добавьте вот эти строки перед тэгом <ItemGroup>:

Код - XML: [Выделить]
  1.   <Choose>
  2.     <When Condition="'$(Configuration)' == 'Revit 2013'">
  3.       <ItemGroup>
  4.         <Reference Include="RevitAPI">
  5.           <HintPath>c:\Program Files\Autodesk\Revit 2013\Program\RevitAPI.dll</HintPath>
  6.           <Private>False</Private>
  7.         </Reference>
  8.         <Reference Include="RevitAPIUI">
  9.           <HintPath>c:\Program Files\Autodesk\Revit 2013\Program\RevitAPIUI.dll</HintPath>
  10.           <Private>False</Private>
  11.         </Reference>
  12.       </ItemGroup>
  13.     </When>
  14.     <When Condition="'$(Configuration)' == 'Revit 2014'">
  15.       <ItemGroup>
  16.         <Reference Include="RevitAPI">
  17.           <HintPath>C:\Program Files\Autodesk\Revit Architecture 2014\RevitAPI.dll</HintPath>
  18.           <Private>False</Private>
  19.         </Reference>
  20.         <Reference Include="RevitAPIUI">
  21.           <HintPath>C:\Program Files\Autodesk\Revit Architecture 2014\RevitAPIUI.dll</HintPath>
  22.           <Private>False</Private>
  23.         </Reference>
  24.       </ItemGroup>
  25.     </When>
  26.     <Otherwise>
  27.       <ItemGroup>
  28.         <Reference Include="RevitAPI">
  29.           <HintPath>d:\Program Files\Autodesk\Revit 2015\RevitAPI.dll</HintPath>
  30.           <Private>False</Private>
  31.         </Reference>
  32.         <Reference Include="RevitAPIUI">
  33.           <HintPath>d:\Program Files\Autodesk\Revit 2015\RevitAPIUI.dll</HintPath>
  34.           <Private>False</Private>
  35.         </Reference>
  36.       </ItemGroup>
  37.     </Otherwise>
  38.   </Choose>

Сохраните файл проекта и перезагрузите проект в Visual Studio. Теперь, меняя конфигурации, будут и меняться ссылки на сборки соответствующей версии Revit.

Таким образом, мы добились результата, при котором простая смена конфигурации будет создавать надстройку для различной версии Revit.

Пример файла проекта можно скачать по ссылке.

Автор: Виктор Чекалин
Автор перевода: Виктор Чекалин

Обсуждение: http://adn-cis.org/forum/index.php?topic=900

Опубликовано 08.08.2014
Отредактировано 09.08.2014 в 09:38:56