# Дальнейшая работа с Zero-Touch

Понимая, как создать проект Zero-Touch, мы можем подробно рассмотреть особенности создания узла, изучив пример ZeroTouchEssentials на Dynamo GitHub.

> Многие стандартные узлы Dynamo, по сути, являются узлами Zero-Touch, как и большинство узлов Math, Color и DateTime.

Для начала скачайте проект ZeroTouchEssentials на странице <https://github.com/DynamoDS/ZeroTouchEssentials>

В Visual Studio откройте файл решения `ZeroTouchEssentials.sln` и выполните сборку.

> Файл `ZeroTouchEssentials.cs` содержит все методы, которые будут импортированы в Dynamo.

Откройте Dynamo и импортируйте `ZeroTouchEssentials.dll`, чтобы получить узлы, на которые мы будем ссылаться в следующих примерах.

Примеры кода извлекаются из [ZeroTouchEssentials.cs](https://github.com/DynamoDS/ZeroTouchEssentials/blob/master/ZeroTouchEssentials/ZeroTouchEssentials.cs). XML-документация удалена для краткости. В каждом примере с помощью кода будет создан узел, приведенный на изображении над ним.

### Входные значения по умолчанию <a href="#default-input-values" id="default-input-values"></a>

Dynamo поддерживает определение значений по умолчанию для входных портов в узле. Значения по умолчанию передаются в узел, если у портов нет соединений. Значения по умолчанию выражаются с помощью механизма указания дополнительных аргументов на C# в соответствии с материалами [Руководства по программированию на C#](https://msdn.microsoft.com/ru-ru/library/dd264739.aspx). По умолчанию задаются следующим образом.

* Задайте для параметров метода значение по умолчанию: `inputNumber = 2.0`

```
namespace ZeroTouchEssentials
{
    public class ZeroTouchEssentials
    {
        // Set the method parameter to a default value
        public static double MultiplyByTwo(double inputNumber = 2.0) 
        {
            return inputNumber * 2.0;
        }
    }
}
```

> 1. Значение по умолчанию отображается при наведении курсора на входной порт узла.

### Возврат нескольких значений <a href="#returning-multiple-values" id="returning-multiple-values"></a>

Возврат нескольких значений — несколько более сложная задача, чем создание нескольких наборов входных данных. В этом случае данные возвращаются с использованием словаря. Записи словаря становятся портами на выходной стороне узла. Порты с возвратом нескольких значений создаются следующим образом.

* Добавьте `using System.Collections.Generic;` для использования `Dictionary<>`.
* Добавьте `using Autodesk.DesignScript.Runtime;` для использования атрибута `MultiReturn`. В данном случае ссылка на DynamoServices.dll содержится в пакете NuGet DynamoServices.
* Добавьте к методу атрибут `[MultiReturn(new[] { "string1", "string2", ... more strings here })]`. Строки ссылаются на ключи в словаре и становятся именами выходных портов.
* Выполните возврат `Dictionary<>` из функции с ключами, совпадающими с именами параметров в атрибуте: `return new Dictionary<string, object>`.

```
using System.Collections.Generic;
using Autodesk.DesignScript.Runtime;

namespace ZeroTouchEssentials
{
    public class ZeroTouchEssentials
    {
        [MultiReturn(new[] { "add", "mult" })]
        public static Dictionary<string, object> ReturnMultiExample(double a, double b)
        {
            return new Dictionary<string, object>

                { "add", (a + b) },
                { "mult", (a * b) }
            };
        }
    }
}
```

> См. этот пример кода в [ZeroTouchEssentials.cs](https://github.com/DynamoDS/ZeroTouchEssentials/blob/9917fd8159afc9e7bdb2944c960155a496e0b2dc/ZeroTouchEssentials/ZeroTouchEssentials.cs#L70)

Узел, возвращающий несколько выходных данных.

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

### Документация, подсказки и поиск <a href="#documentation-tooltips-and-search" id="documentation-tooltips-and-search"></a>

Рекомендуется прикреплять к узлам Dynamo документацию, описывающую функции узла, входные и выходные данные, теги поиска и т. д. Для этого используются теги XML-документации. XML-документация создается следующим образом.

* Документацией считается любой текст комментария после значка «///» (три наклонные черты).
  * Например: `/// Documentation text and XML goes here` (Текст документации и XML размещается здесь)
* После трех наклонных черт создайте теги XML над методами, которые Dynamo будет считывать при импорте DLL-файла.
  * Например: `/// <summary>...</summary>`
* Включите XML-документацию в Visual Studio, выбрав `Project > [Project] Properties > Build > Output` и установив флажок `Documentation file` (Файл XML-документации).

> 1. Visual Studio создаст XML-файл в указанной папке.

Типы тегов:

* `/// <summary>...</summary>` обозначает основную документацию для узла, которая отображается в виде подсказки над узлом в строке поиска слева.
* `/// <param name="inputName">...</param>` создает документацию для конкретных входных параметров.
* `/// <returns>...</returns>` создает документацию для выходного параметра.
* `/// <returns name = "outputName">...</returns>` создает документацию для нескольких выходных параметров.
* `/// <search>...</search>` сопоставляет узел с результатами поиска на основе списка, разделенного запятыми. Например, если создать узел, который разделяет сетку, можно добавить такие теги, как mesh, subdivision и catmull-clark.

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

```
using Autodesk.DesignScript.Geometry;

namespace ZeroTouchEssentials
{
    public class ZeroTouchEssentials
    {
        /// <summary>
        /// This method demonstrates how to use a native geometry object from Dynamo
        /// in a custom method
        /// </summary>
        /// <param name="curve">Input Curve. This can be of any type deriving from Curve, such as NurbsCurve, Arc, Circle, etc</param>
        /// <returns>The twice the length of the Curve </returns>
        /// <search>example,curve</search>
        public static double DoubleLength(Curve curve)
        {
            return curve.Length * 2.0;
        }
    }
}
```

> См. пример кода в [ZeroTouchEssentials.cs](https://github.com/DynamoDS/ZeroTouchEssentials/blob/9917fd8159afc9e7bdb2944c960155a496e0b2dc/ZeroTouchEssentials/ZeroTouchEssentials.cs#L80)

Обратите внимание на содержимое этого примера узла.

> 1. Сводка узла.
> 2. Описание входных данных.
> 3. Описание выходных данных.

#### Практические советы по работе с описаниями узлов Dynamo

В описаниях узлов содержатся краткие описания функций и выходных данных узла. В Dynamo они отображаются в двух местах:

* во всплывающей подсказке для узла;
* в обозревателе документации.

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

**Обзор**

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

Используйте регистр по предложениям (первое слово предложения и любые имена собственные с заглавной буквы); без точки в конце.

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

Всегда уделяйте первостепенное внимание ясности, даже если это означает отклонение от этих рекомендаций.

**Рекомендации**

| Можно                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   | Нельзя                                                                                                                                                                                                                                                                                                                                                                                                                                                          |
| --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| <p>Начинайте описание с глагола в третьем лице.</p><ul><li>Пример: <em>Determines</em> if one geometry object intersects with another</li></ul>                                                                                                                                                                                                                                                                                                                                                                                                                                         | <p>Не используйте глаголы во втором лице или существительные.</p><ul><li>Пример: <em>Determine</em> if one geometry object intersects with another</li></ul>                                                                                                                                                                                                                                                                                                    |
| <p>Используйте Returns, Creates или другой описательный глагол вместо Gets.</p><ul><li>Пример: <em>Returns</em> a Nurbs representation of a surface</li></ul>                                                                                                                                                                                                                                                                                                                                                                                                                           | <p>Не используйте слова Get или Gets. Они менее специфичны и могут быть интерпретированы по-разному.</p><ul><li>Пример: <em>Gets</em> a Nurbs representation of the surface</li></ul>                                                                                                                                                                                                                                                                           |
| <p>Когда речь идет о входных данных, используйте given или input либо другие термины вместо specified. По возможности опускайте слова given и input, чтобы упростить описание и уменьшить количество слов.</p><ul><li>Пример: Deletes the <em>given</em> file</li><li>Пример: Projects a curve along the <em>given</em> projection direction onto <em>given</em> base geometry</li></ul><p>Можно использовать слово specified, если оно не ссылается непосредственно на входные данные.</p><ul><li>Пример: Writes text content to a file <em>specified</em> by the given path</li></ul> | <p>Когда речь идет о входных данных, чтобы обеспечить единообразие, не используйте слово specified или любой другой термин, кроме given или input. Не смешивайте слова given и input в одном и том же описании, если только это не требуется для ясности.</p><ul><li>Пример: Deletes the <em>specified</em> file</li><li>Пример: Projects an <em>input</em> curve along a <em>given</em> projection direction onto a <em>specified</em> base geometry</li></ul> |
| <p>При первом упоминании входных данных используйте артикль a или an. Используйте the given или the input вместо a или an по мере необходимости для ясности.</p><ul><li>Пример: Sweeps <em>a</em> curve along the path curve</li></ul>                                                                                                                                                                                                                                                                                                                                                  | <p>Не используйте слово this, когда впервые ссылаетесь на входные данные.</p><ul><li>Пример: Sweeps <em>this</em> curve along the path curve</li></ul>                                                                                                                                                                                                                                                                                                          |
| <p>При первом упоминании выходных данных или другого существительного, которое обозначает цель операции узла, используйте a или an. Используйте слово the только в сочетании с input или given.</p><ul><li>Пример: Copies <em>a</em> file</li><li>Пример: Copies <em>the given</em> file</li></ul>                                                                                                                                                                                                                                                                                      | <p>При первом упоминании выходных данных или другого существительного, которое обозначает цель операции узла, не используйте слово the самостоятельно.</p><ul><li>Пример: Copies <em>the</em> file</li></ul>                                                                                                                                                                                                                                                    |
| <p>Пишите с заглавной буквы первое слово в предложении, имена собственные и другие существительные, которые обычно начинаются с прописной буквы.</p><ul><li>Пример: Returns the intersection of two <em>BoundingBoxes</em></li></ul>                                                                                                                                                                                                                                                                                                                                                    | <p>Не используйте прописные буквы для общих геометрических объектов и понятий, если в этом нет необходимости.</p><ul><li>Пример: Scales non-uniformly around the given <em>Plane</em></li></ul>                                                                                                                                                                                                                                                                 |
| <p>Пишите слово Boolean с заглавной буквы. Пишите слова True и False с заглавной буквы, если речь идет о выводе логических значений.</p><ul><li>Пример: Returns <em>true</em> if the two values are different</li><li>Пример: Converts a string to all uppercase or all lowercase characters based on a <em>Boolean</em> parameter</li></ul>                                                                                                                                                                                                                                            | <p>Не используйте нижний регистр для слова Boolean. Не пишите слова True и False со строчной буквы, если речь идет о выводе логических значений.</p><ul><li>Пример: Returns <em>true</em> if the two values are different</li><li>Пример: Converts a string to all uppercase characters or all lowercase characters based on a <em>boolean</em> parameter</li></ul>                                                                                             |

#### Предупреждения и ошибки узлов Dynamo

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

Рекомендации по обеспечению согласованности и экономии времени при написании или обновлении предупреждений и сообщений об ошибках узлов см. на странице Wiki [Шаблон содержимого: предупреждения и ошибки узлов](https://github.com/DynamoDS/Dynamo/wiki/Content-Pattern:-Node-Warnings-and-Errors).

### Объекты <a href="#objects" id="objects"></a>

В Dynamo отсутствует ключевое слово `new`, поэтому объекты создаются с использованием статических методов конструирования. Объекты создаются следующим образом.

* Сделайте конструктор внутренним `internal ZeroTouchEssentials()`, если не требуется иное.
* Постройте объект с помощью статического метода, например `public static ZeroTouchEssentials ByTwoDoubles(a, b)`.

> Примечание. В Dynamo используется префикс «By», указывающий на то, что статический метод является конструктором. Использовать этот префикс необязательно, но с ним ваша библиотека будет соответствовать общепринятому стилю Dynamo.

```
namespace ZeroTouchEssentials
{
    public class ZeroTouchEssentials
    {
        private double _a;
        private double _b;

        // Make the constructor internal
        internal ZeroTouchEssentials(double a, double b)
        {
            _a = a;
            _b = b;
        }

        // The static method that Dynamo will convert into a Create node
        public static ZeroTouchEssentials ByTwoDoubles(double a, double b)
        {
            return new ZeroTouchEssentials(a, b);
        }
    }
}
```

> См. пример кода в [ZeroTouchEssentials.cs](https://github.com/DynamoDS/ZeroTouchEssentials/blob/9917fd8159afc9e7bdb2944c960155a496e0b2dc/ZeroTouchEssentials/ZeroTouchEssentials.cs#L26)

После импорта DLL-файла ZeroTouchEssentials в библиотеке появится узел ZeroTouchEssentials. Этот объект можно создать с помощью узла `ByTwoDoubles`.

### Использование типов геометрии Dynamo <a href="#using-dynamo-geometry-types" id="using-dynamo-geometry-types"></a>

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

* Вставьте ссылку на файл ProtoGeometry.dll в проект, добавив `using Autodesk.DesignScript.Geometry;` в верхней части файла C# и добавив пакет NuGet библиотеки ZeroTouchLibrary в проект.
* **Важно.** Дополнительную информацию об управлении ресурсами геометрии, возврат которых не выполняется из функций, см. в приведенном ниже разделе **Удаление/использование операторов**.

> Примечание. Геометрические объекты Dynamo используются так же, как и любые другие объекты, передаваемые функциям.

```
using Autodesk.DesignScript.Geometry;

namespace ZeroTouchEssentials
{
    public class ZeroTouchEssentials
    {
        // "Autodesk.DesignScript.Geometry.Curve" is specifying the type of geometry input, 
        // just as you would specify a double, string, or integer 
        public static double DoubleLength(Autodesk.DesignScript.Geometry.Curve curve)
        {
            return curve.Length * 2.0;
        }
    }
}
```

> См. пример кода в [ZeroTouchEssentials.cs](https://github.com/DynamoDS/ZeroTouchEssentials/blob/9917fd8159afc9e7bdb2944c960155a496e0b2dc/ZeroTouchEssentials/ZeroTouchEssentials.cs#L86)

Узел, который получает длину кривой и удваивает ее.

> 1. В качестве входных данных для этого узла можно использовать геометрию кривой.

### Удаление/использование операторов <a href="#disposeusing-statements" id="disposeusing-statements"></a>

Если вы не используете Dynamo версии 2.5 или более поздней, управлять геометрическими ресурсами, которые не возвращены из функций, необходимо вручную. В Dynamo 2.5 и более поздних версий геометрические ресурсы обрабатываются системой, однако в сложных сценариях и для сокращения объема используемой памяти вы можете удалять геометрию вручную. Движок Dynamo обрабатывает все геометрические ресурсы, которые возвращаются из функций. Невозвращенные геометрические ресурсы можно обработать вручную следующими способами.

* С помощью оператора using:

  ```
  using (Point p1 = Point.ByCoordinates(0, 0, 0))
  {
    using (Point p2 = Point.ByCoordinates(10, 10, 0))
    {
        return Line.ByStartPointEndPoint(p1, p2);
    }
  }
  ```

  > [Документация](https://msdn.microsoft.com/ru-ru/library/yh598w02.aspx) об использовании оператора using
  >
  > Дополнительные сведения о новых функциях обеспечения стабильности, появившихся в Dynamo 2.5, см. в разделе [Повышение стабильности геометрии в Dynamo](https://forum.dynamobim.com/t/dynamo-geometry-stability-improvements-request-for-feedback/39297)
* При выполнении вызовов Dispose вручную:

  ```
  Point p1 = Point.ByCoordinates(0, 0, 0);
  Point p2 = Point.ByCoordinates(10, 10, 0);
  Line l = Line.ByStartPointEndPoint(p1, p2);
  p1.Dispose();
  p2.Dispose();
  return l;
  ```

### Миграция <a href="#migrations" id="migrations"></a>

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

* Создайте файл `.xml` в той же папке, что и файл `.dll`, в следующем формате: ИмяФайлаDLL.Migrations.xml.
* В диалоговом окне `.xml` создайте один элемент `<migrations>...</migrations>`.
* Внутри элемента миграции создайте элементы `<priorNameHint>...</priorNameHint>` для каждого изменения имени.
* При каждом изменении имени укажите `<oldName>...</oldName>` и `<newName>...</newName>`

> 1. Щелкните правой кнопкой мыши и выберите `Add > New Item` (Добавить > Новый элемент).
> 2. Выберите `XML File` (XML-файл).
> 3. В нашем проекте мы присвоим файлу миграции имя `ZeroTouchEssentials.Migrations.xml`.

Этот код указывает Dynamo, что узлы с именем `GetClosestPoint` теперь называются `ClosestPointTo`.

```
<?xml version="1.0"?>
<migrations>
  <priorNameHint>
    <oldName>Autodesk.DesignScript.Geometry.Geometry.GetClosestPoint</oldName>
    <newName>Autodesk.DesignScript.Geometry.Geometry.ClosestPointTo</newName>
  </priorNameHint>
</migrations>
```

> См. пример кода в файле [ProtoGeometry.Migrations.xml](https://github.com/DynamoDS/Dynamo/blob/master/extern/ProtoGeometry/ProtoGeometry.Migrations.xml)

### Универсальные типы <a href="#generics" id="generics"></a>

Zero-Touch в настоящее время не поддерживает использование универсальных типов. Их можно использовать, но не в коде, который импортируется напрямую, если тип не задан. Универсальные методы, свойства и классы, у которых нет типа, нельзя предоставить.

В примере ниже узел Zero-Touch типа `T` не будет импортирован. Если остальные компоненты библиотеки импортируются в Dynamo, возникнут исключения отсутствующих типов.

```
public class SomeGenericClass<T>
{
    public SomeGenericClass()
    {
        Console.WriteLine(typeof(T).ToString());
    }  
}
```

При использовании универсального типа с типом, заданным в этом примере, импорт в Dynamo будет выполнен.

```
public class SomeWrapper
{
    public object wrapped;
    public SomeWrapper(SomeGenericClass<double> someConstrainedType)
    {
        Console.WriteLine(this.wrapped.GetType().ToString());
    }
}
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://primer2.dynamobim.org/ru/1_developer_primer_intro/3_developing_for_dynamo/4-going-further-with-zero-touch.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
