Actualización de paquetes y bibliotecas de Dynamo para Dynamo 2.x
Last updated
Last updated
Dynamo 2.0 es una versión principal y se han modificado o eliminado algunas API. Uno de los mayores cambios que afectará a los autores de nodos y paquetes es el paso a un formato de archivo JSON.
En general, los autores de nodos Zero-Touch tendrán poco o ningún trabajo que hacer para que sus paquetes funcionen en 2.0.
Los nodos de interfaz de usuario y aquellos que proceden directamente de NodeModel requerirán más trabajo para funcionar en 2.x.
Es posible que los autores de extensiones también deban realizar algunos cambios en función de la cantidad de API de Dynamo Core que utilicen en sus extensiones.
No incluya archivos .dll de Dynamo o de DynamoRevit en el paquete. Dynamo ya cargará estos archivos. Si compila una versión diferente a la que ha cargado el usuario (es decir, si distribuye Dynamo Core 1.3, pero el usuario ejecuta el paquete en Dynamo 2.0), se producirán extraños errores de ejecución. Esto incluye archivos .dll como DynamoCore.dll
, DynamoServices.dll
, DSCodeNodes.dll
y ProtoGeometry.dll
.
No agrupe y distribuya newtonsoft.json.net
con el paquete si puede evitarlo. Dynamo 2.x también cargará este archivo dll. Puede producirse el mismo problema indicado anteriormente.
No agrupe y distribuya CEFSharp
con el paquete si puede evitarlo. Dynamo 2.x también cargará este archivo dll. Puede producirse el mismo problema indicado anteriormente.
En general, evite compartir dependencias con Dynamo o Revit si necesita controlar la versión de esa dependencia.
1) Al abrir un gráfico, algunos nodos tienen varios puertos con el mismo nombre, pero el gráfico presenta un aspecto correcto al guardar. Este problema puede tener varias causas.
La principal causa habitual es que el nodo se ha creado con un constructor que ha vuelto a crear los puertos. En su lugar, debería haberse utilizado un constructor que cargara los puertos. Estos constructores suelen estar marcados con [JsonConstructor]
. Consulte los ejemplos siguientes:
Esto puede deberse a lo siguiente:
No se ha encontrado ningún [JsonConstructor]
coincidente o no se han transferido los archivos Inports
y Outports
del archivo .dyn de JSON.
Había dos versiones de JSON.net cargadas en el mismo proceso al mismo tiempo, lo que provocaba fallos en el tiempo de ejecución de .net, por lo que el atributo [JsonConstructor]
no podía utilizarse correctamente para marcar el constructor.
DynamoServices.dll con una versión diferente a la versión actual de Dynamo se ha incluido con el paquete, lo que provoca que el tiempo de ejecución de .net no identifique el atributo [MultiReturn]
, por lo que los nodos Zero-Touch marcados con varios atributos no podrán aplicarlos. Es posible que un nodo devuelva una única salida de diccionario en lugar de varios puertos.
2) Faltan completamente nodos al cargar el gráfico con algunos errores en la consola.
Esto puede producirse si la deserialización falla por algún motivo. Es recomendable serializar solo las propiedades necesarias. Podemos utilizar [JsonIgnore]
en propiedades complejas que no sea necesario cargar o guardar para omitirlas como, por ejemplo, function pointer, delegate, action,
o event
, etc. No deben serializarse, ya que normalmente fallarán durante la deserialización y provocarán un error de ejecución.
Organización de nodos personalizados en librarie.js
Problemas conocidos
La coincidencia de un nombre de nodo y un nombre de categoría personalizados en el mismo nivel en librarie.js provoca un comportamiento inesperado. QNTM-3653: evite utilizar los mismos nombres para la categoría y los nodos.
Los comentarios se convertirán en comentarios de bloque en lugar de comentarios de línea.
Los nombres de tipo cortos se sustituirán por nombres completos. Por ejemplo, si no ha especificado un tipo al cargar de nuevo el nodo personalizado, aparecerá var[]..[]
, ya que este es el tipo por defecto.
En Dynamo 2.0, los tipos de lista y diccionario se han dividido y se ha cambiado la sintaxis para crear listas y diccionarios. Las listas se inicializan mediante []
mientras que los diccionarios utilizan {}
.
Si anteriormente utilizaba el atributo DefaultArgument
para marcar parámetros en los nodos Zero-Touch y utilizaba la sintaxis de lista para establecer por defecto una lista específica como someFunc([DefaultArgument("{0,1,2}")])
, esto ya no será válido y deberá modificar el fragmento de código de DesignScript para utilizar la nueva sintaxis de inicialización para las listas.
Como se ha indicado anteriormente, no distribuya archivos dll de Dynamo con los paquetes (DynamoCore
, DynamoServices
, etc.).
Los nodos Node Model son los que más trabajo requieren para actualizarse a Dynamo 2.x. En un nivel alto, deberá implementar constructores que solo se usen para cargar los nodos desde json, además de los constructores nodeModel habituales que se usan para crear nuevas instancias de los tipos de nodos. Para diferenciar entre estos, se marcan los constructores de tiempo de carga con [JsonConstructor]
, que es un atributo de newtonsoft.Json.net.
Por lo general, los nombres de los parámetros del constructor deben coincidir con los nombres de las propiedades JSON, aunque esta asignación se complica más si se modifican los nombres serializados mediante atributos [JsonProperty]. Consulte la documentación de Json.net para obtener más información.
El cambio más habitual requerido para actualizar nodos derivados de la clase base NodeModel
(u otras clases base de Dynamo Core, por ejemplo, DSDropDownBase
) es la necesidad de añadir un constructor JSON a la clase.
El constructor original sin parámetros seguirá gestionando la inicialización de un nuevo nodo creado en Dynamo (por ejemplo, mediante la biblioteca). El constructor JSON es necesario para inicializar un nodo deserializado (cargado) desde un archivo .dyn o .dyf guardado.
El constructor JSON se diferencia del constructor base en que tiene parámetros PortModel
para inPorts
y outPorts
, que proporciona la lógica de carga JSON. La llamada para registrar los puertos del nodo no es necesaria aquí, ya que los datos existen en el archivo .dyn. A continuación, se muestra un constructor JSON de ejemplo:
using Newtonsoft.Json; //New dependency for Json
………
[JsonConstructor] //Attribute required to identity the Json constructor
//Minimum constructor implementation. Note that the base method invocation must also be present.
FooNode(IEnumerable<PortModel> inPorts, IEnumerable<PortModel> outPorts) : base(inPorts, outPorts) { }
Esta sintaxis :base(Inports,outPorts){}
llama al constructor base nodeModel
y le transfiere los puertos deserializados.
No es necesario repetir en este constructor la lógica especial presente en el constructor de clase que implicará la inicialización de datos específicos serializados en el archivo .dyn (por ejemplo, la configuración del registro del puerto, la estrategia de encaje, etc.), ya que estos valores se pueden leer desde JSON.
Esta es la diferencia principal entre el constructor JSON y los constructores que no son JSON para nodeModels. Se llama a los constructores JSON al cargar desde un archivo y se transfieren los datos cargados a estos. Sin embargo, debe duplicarse otra lógica de usuario en el constructor JSON (por ejemplo, mediante la inicialización de controladores de eventos para el nodo o el enlace).
Aquí se pueden encontrar ejemplos en el repositorio de DynamoSamples -> ButtonCustomNodeModel, DropDown o SliderCustomNodeModel.
Anteriormente, un desarrollador podía serializar y deserializar datos específicos del modelo en el documento xml a través de los métodos SerializeCore
y DeserializeCore
. Estos métodos siguen existiendo en la API, pero se dejarán de utilizar en una versión futura de Dynamo (puede encontrar un ejemplo aquí). Con la implementación de JSON.NET actual, las propiedades public
de la clase derivada NodeModel se pueden serializar directamente en el archivo .dyn. JSON.Net proporciona varios atributos para controlar cómo se serializa la propiedad.
Este ejemplo que especifica un PropertyName
se encuentra aquí, en el repositorio de Dynamo.
[JsonProperty(PropertyName = "InputValue")]
public DSColor DsColor {...
Nota
Si crea su propia clase de conversor de JSON.net, Dynamo no dispone actualmente de un mecanismo para permitir su inserción en los métodos de carga y almacenamiento, por lo que, aunque marque la clase con el atributo [JsonConverter]
, es posible que no se utilice; en su lugar, puede llamar al conversor directamente en el establecedor o el captador. //TODO necesita confirmación de esta limitación. Es recomendable proporciona todas las pruebas posibles.
Aquí se proporciona un ejemplo que especifica un método de serialización para convertir la propiedad en una cadena en el repositorio de Dynamo.
[JsonProperty("MeasurementType"), JsonConverter(typeof(StringEnumConverter))]
public ConversionMetricUnit SelectedMetricConversion{...
Para las propiedades public
que no se han diseñado para la serialización, es necesario añadir el atributo [JsonIgnore]
. Cuando se guardan los nodos en el archivo .dyn, esto garantiza que el mecanismo de serialización no omitirá estos datos y estos no provocarán consecuencias inesperadas cuando se abra de nuevo el gráfico. Aquí puede encontrar un ejemplo es esto en el repositorio de Dynamo.
Como se ha mencionado anteriormente, los métodos SerializeCore
y DeserializeCore
se utilizaban anteriormente para guardar y cargar nodos en el archivo .dyn xml. Además, también se utilizaban para guardar y cargar el estado del nodo para deshacer/rehacer y aún se utilizan. Si desea implementar funciones complejas de deshacer/rehacer para el nodo de interfaz de usuario nodeModel, deberá implementar estos métodos y serializarlos en el objeto de documento XML proporcionado como parámetro para estos métodos. Por lo general, este caso de uso es bastante infrecuente, excepto en los nodos de interfaz de usuario complejos.
Una incidencia habitual en los nodos nodeModel afectados por los cambios en las API de la versión 2.0 es el registro de puertos en el constructor de nodos. Si observa los ejemplos del repositorio de Dynamo o DynamoSamples, habrá detectado el uso de los métodos InPortData.Add()
o OutPortData.Add()
. Anteriormente, en la API de Dynamo, las propiedades públicas InPortData
y OutPortData
se marcaban como obsoletas. En la versión 2.0, estas propiedades se han eliminado. Los desarrolladores deberían utilizar ahora los métodos InPorts.Add()
y OutPorts.Add()
. Además, estos dos métodos Add()
presentan firmas ligeramente diferentes:
InPortData.Add(new PortData("Port Name", "Port Description")); //Old version valid in 1.3 but now deprecated
frente a
InPorts.Add(new PortModel(PortType.Input, this, new PortData("Port Name", "Port Description"))); //Recommended 2.0
Puede encontrar ejemplos de código convertido aquí, en el repositorio de Dynamo: > DynamoConvert.cs o FileSystem.cs.
El otro caso de uso común que se ve afectado por los cambios en las API de la versión 2.0 está relacionado con los métodos utilizados habitualmente en el método BuildAst()
para determinar el comportamiento de los nodos en función de la presencia o la ausencia de conectores de puerto. Anteriormente, HasConnectedInput(index)
se utilizaba para validar un estado de puerto conectado. Los desarrolladores deben utilizar ahora la propiedad InPorts[0].IsConnected
para comprobar el estado de conexión del puerto. Un ejemplo de esto se puede encontrar en ColorRange.cs, en el repositorio de Dynamo.
Veamos cómo actualizar un nodo de interfaz de usuario 1.3 a Dynamo 2.x.
Todo lo que necesitamos hacer con esta clase nodeModel
para que se cargue y se guarde correctamente en la versión 2.0 es añadir un jsonConstructor a fin de gestionar la carga de los puertos. Simplemente transferimos los puertos en el constructor base; esta implementación está vacía.
Nota: No llame a RegisterPorts()
ni a ninguna variación de este parámetro en el JsonConstructor, ya que se utilizarán los atributos de parámetros de entrada y salida de la clase de nodo para crear nuevos puertos. Esto no es lo que queremos, ya que deseamos utilizar los puertos cargados que se han transferido al constructor.
En este ejemplo, se añade el constructor JSON de carga mínima posible. ¿Pero qué pasa si necesitamos usar una lógica de construcción más compleja, como configurar algunas escuchas para la gestión de eventos dentro del constructor? El vínculo al siguiente ejemplo obtenido de
DynamoSamples Repo aparece arriba en la JsonConstructors Section
de este documento.
A continuación, se muestra un constructor más complejo para un nodo de interfaz de usuario:
Cuando añadimos un constructor JSON para cargar este nodo desde un archivo, debemos volver a crear parte de esta lógica, pero tenga en cuenta que no incluimos el código que crea los puertos, establece el encaje o define los valores por defecto para las propiedades que podemos cargar desde el archivo.
Tenga en cuenta que otras propiedades públicas serializadas en JSON como ButtonText
y WindowText
no se añadirán como parámetros explícitos para el constructor; JSON.net las define automáticamente mediante los establecedores de esas propiedades.