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

19/07/2013

Свойство IsShared для класса FamilyParameter

Довольно давно мы обсуждали способ как получить доступ к идентификатору общего параметра семейства (GUID) с помощью рефлексии. Если вы новичок в данном вопросе, вы можете ознакомиться с более подробной статьей  Reflection in .NET на сайте CodeProject (на англ.).

Виктор Чекалин также столкнулся с этой проблемой и предложил более элегантное решение.

Ниже представлен наш диалог с обсуждением проблемы.

Вопрос: Почему класс FamilyParameter не имеет свойства IsShared, так же как и класс Parameter? Мне нужно получить всех параметров семейства, все их свойства и значения, включая GUID.

Сейчас, когда я пытаюсь получить значения свойства GUID объекта класса FamilyParameter и при этом параметр не является общим, Revit выбрасывает исключение InvalidOperationException. Единственный способ, как я могу узнать является ли параметр общим или нет, попытаться получить значение свойства GUID и обработать исключение, если параметр не общий.

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

Почему разработчика API реализовали такое довольно странное поведение и не добавили свойство IsShared в класс FamilyParameter? Можно ведь было возвращать null, если параметр не является общим, а не выбрасывать исключение.

Ответ: Прошу прощения за столь странное поведение. Обойти это ограничение и получить доступ к этим параметром можно используя рефлексию.

Отклик на ответ: Да, кажется этот способ действительно может мне помочь.

Я посмотрел код RevitAPI.dll с помощью рефлектора и мне стало еще более непонятным почему разработчики Revit API не добавили свойство IsShared для FamilyParameter. Ведь класс FamilyParameter является всего лишь оберткой над классом Parameter и чтобы добавить свойство IsShared нужно написать всего лишь пару строк кода:

Код - C#: [Выделить]
  1.  
  2. public bool IsShared
  3. {
  4.   get { return getParameter().IsShared; }
  5. }

Повторно прочитав вашу статью, я кажется понял, почему они так и не добавили это свойство. Свойства GUID и IsShared были добавлены в класс Parameter только в Revit 2011. Могу предположить что это простая оплошность и они забыли добавить новые свойства также и в класс FamilyParameter. Возможно я ошибаюсь.

Надеюсь это свойство будет добавлено в следующих версиях API. Насколько я вижу в комментариях к статье, не только я ожидаю свойство IsShared.

Реализация метода-расширения IsShared для класса FamilyParameter

Основываясь на вашем примере в статье, я написал простой метод-расширение:

Код - C#: [Выделить]
  1.  
  2.   public static bool IsShared(
  3.     this FamilyParameter familyParameter )
  4.   {
  5.     MethodInfo mi = familyParameter
  6.       .GetType()
  7.       .GetMethod( "getParameter",
  8.         BindingFlags.Instance
  9.         | BindingFlags.NonPublic );
  10.  
  11.     if( null == mi )
  12.     {
  13.       throw new InvalidOperationException(
  14.         "Could not find getParameter method" );
  15.     }
  16.  
  17.     var parameter = mi.Invoke( familyParameter,
  18.       new object[] { } ) as Parameter;
  19.  
  20.     return parameter.IsShared;
  21.   }

Я использовал внутренний метод getParameter вместо поля m_Parameter, так как не рекомендуется обращаться к полям класса из другого класса. Также этот метод используется в коде в большинстве случаев, которые я видел используя рефлектор, а не поле m_Parameter.

Использование метода-расширения

Использование нового метода довольно очевидно:

Код - C#: [Выделить]
  1.  
  2.   foreach( FamilyParameter fp in mgr.Parameters )
  3.   {
  4.     if( fp.IsShared() )
  5.     {
  6.       familyTypeParameter.Guid = fp.GUID;
  7.     }
  8.   }

Метод работает гораздо быстрее чем обработка и перехват исключения, например так:

Код - C#: [Выделить]
  1.  
  2.   try { var guid = parameter.GUID; }
  3.   catch() {}

Спасибо еще раз, что напомнил мне о рефлексии.

Ответ: Большое спасибо, Виктор, за исследование, отличную реализацию и  что поделился с нами своим решением.

Источник: http://thebuildingcoder.typepad.com/blog/2012/09/familyparameter-isshared-property.html

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

Опубликовано 19.07.2013
Отредактировано 19.07.2013 в 10:51:02