Aggiornamento di pacchetti e librerie di Dynamo per Dynamo 2.x
Introduzione:
Dynamo 2.0 è una release principale e alcune API sono state modificate o rimosse. Una delle modifiche più importanti che influiranno sugli autori di nodi e pacchetti è il passaggio al formato di file JSON.
In generale, gli autori dei nodi zero-touch dovranno fare poco o nulla per far funzionare i loro pacchetti nella versione 2.0.
I nodi dell'interfaccia utente e i nodi che derivano direttamente da NodeModel richiederanno più lavoro per l'esecuzione nella versione 2.x.
Anche gli autori di estensioni potrebbero dover apportare alcune modifiche, a seconda della quantità di API di Dynamo Core che utilizzano nelle loro estensioni.
Regole generali di creazione di pacchetti:
Non aggregare i file .dll di Dynamo o DynamoRevit con il pacchetto. Questi file DLL verranno già caricati da Dynamo. Se si aggrega una versione diversa da quella caricata dall'utente (ad esempio si distribuisce Dynamo Core 1.3 ma l'utente sta eseguendo il pacchetto in Dynamo 2.0), si verificheranno inspiegabili bug di runtime. Ciò include file .dll come
DynamoCore.dll
,DynamoServices.dll
,DSCodeNodes.dll
eProtoGeometry.dll
.Non aggregare e distribuire
newtonsoft.json.net
con il pacchetto se è possibile evitarlo. Questo file .dll verrà caricato anche da Dynamo 2.x. Può verificarsi lo stesso problema descritto in precedenza.Non aggregare e distribuire
CEFSharp
con il pacchetto se è possibile evitarlo. Questo file .dll verrà caricato anche da Dynamo 2.x. Può verificarsi lo stesso problema descritto in precedenza.In generale, evitare di condividere le dipendenze con Dynamo o Revit se è necessario controllare la versione di tale dipendenza.
Problemi comuni:
1) All'apertura di un grafico, alcuni nodi presentano più porte con lo stesso nome, ma il grafico risultava corretto al momento del salvataggio. Questo problema può avere varie cause.
La causa principale comune è che il nodo è stato creato utilizzando un costruttore che ha ricreato le porte. Invece, avrebbe dovuto essere utilizzato un costruttore che ha caricato le porte. Questi costruttori sono generalmente contrassegnati [JsonConstructor]
. Per alcuni esempi, vedere di seguito.
Ciò può verificarsi perché:
Semplicemente non era presente un valore
[JsonConstructor]
corrispondente o non è stato trasferito il valoreInports
eOutports
dal file .dyn JSON.Sono state caricate due versioni di JSON.net nello stesso processo contemporaneamente, causando un errore di runtime del file.net, pertanto l'attributo
[JsonConstructor]
non può essere utilizzato correttamente per contrassegnare il costruttore.Il file DynamoServices.dll con una versione diversa da quella corrente di Dynamo è stato aggregato con il pacchetto e causa la mancata identificazione dell'attributo
[MultiReturn]
in fase di runtime del file .net, pertanto i nodi zero-touch contrassegnati con vari attributi non verranno applicati. Potrebbe verificarsi che un nodo restituisca un singolo output del dizionario anziché più porte.
2) I nodi risultano completamente mancanti durante il caricamento del grafico con alcuni errori nella console.
Ciò potrebbe succedere se la deserializzazione non è riuscita per qualche motivo. È consigliabile serializzare solo le proprietà necessarie. È possibile utilizzare
[JsonIgnore]
in proprietà complesse che non è necessario caricare o salvare per ignorarle. Proprietà comefunction pointer, delegate, action,
oevent
e così via non dovrebbero essere serializzate, perché di solito non vengono deserializzate e causano un errore di runtime.
Aggiornamento in profondità:
Nodi personalizzati 1.3 - > 2.0
Organizzazione di nodi personalizzati in librarie.js
Problemi noti:
Un nome di nodo personalizzato e un nome di categoria coincidenti allo stesso livello in librarie.js causano un funzionamento imprevisto. QNTM-3653: evitare di utilizzare gli stessi nomi per la categoria e i nodi.
I commenti verranno convertiti in commenti di blocco anziché in commenti di riga.
I nomi di tipo breve verranno sostituiti con nomi completi. Ad esempio, se non è stato specificato un tipo quando si carica nuovamente il nodo personalizzato, verrà visualizzato
var[]..[]
, poiché questo è il tipo di default.
Nodi zero-touch 1.3 -> 2.0
In Dynamo 2.0 i tipi di elenco e dizionario sono stati divisi e la sintassi per la creazione di elenchi e dizionari è stata modificata. Gli elenchi vengono inizializzati utilizzando
[]
, mentre i dizionari usano{}
. Se in precedenza si utilizzava l'attributoDefaultArgument
per contrassegnare i parametri sui nodi zero-touch e si usava la sintassi dell'elenco per impostare come default un elenco specifico comesomeFunc([DefaultArgument("{0,1,2}")])
, questo metodo non sarà più valido e sarà necessario modificare il frammento DesignScript per utilizzare la nuova sintassi di inizializzazione per gli elenchi.Come indicato in precedenza, non distribuire i file .dll di Dynamo con i pacchetti. (
DynamoCore
,DynamoServices
e così via).
Nodi NodeModel 1.3 -> 2.0
I nodi NodeModel richiedono la maggior parte del lavoro per eseguire l'aggiornamento a Dynamo 2.x. A livello generale, sarà necessario implementare i costruttori che verranno utilizzati solo per caricare i nodi dal file JSON, oltre ai normali costruttori di NodeModel usati per creare nuove istanze dei tipi di nodi. Per differenziarli, contrassegnare i costruttori del tempo di caricamento con [JsonConstructor]
, che è un attributo di newtonsoft.Json.net.
I nomi dei parametri nel costruttore dovrebbero in genere corrispondere ai nomi delle proprietà JSON, sebbene questo mappaggio risulti più complicato se si sostituiscono i nomi serializzati con gli attributi [JsonProperty]. Per ulteriori informazioni, vedere la documentazione sui file Json.net.
Costruttori di file JSON
La modifica più comune necessaria per l'aggiornamento dei nodi derivati dalla classe di base NodeModel
(o da altre classi di base di Dynamo Core, ad esempio DSDropDownBase
) è la necessità di aggiungere un costruttore JSON alla classe.
Il costruttore senza parametri originale gestirà comunque l'inizializzazione di un nuovo nodo creato in Dynamo (ad esempio tramite la libreria). Il costruttore JSON è necessario per inizializzare un nodo deserializzato (caricato) da un file .dyn o .dyf salvato.
Il costruttore JSON è diverso dal costruttore di base in quanto contiene i parametri PortModel
per inPorts
e outPorts
, forniti dalla logica di caricamento JSON. La chiamata per la registrazione delle porte per il nodo non è necessaria in questo caso, poiché esistono i dati nel file .dyn. Un esempio di costruttore JSON è simile al seguente:
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) { }
Questa sintassi :base(Inports,outPorts){}
chiama il costruttore di base nodeModel
e vi trasferisce le porte deserializzate.
Non è necessario ripetere in questo costruttore qualsiasi logica speciale presente nel costruttore della classe che implica l'inizializzazione di dati specifici serializzati nel file .dyn (ad esempio, l'impostazione della registrazione della porta, della strategia di collegamento e così via), poiché questi valori possono essere letti dal file JSON.
Questa è la differenza principale tra il costruttore JSON e i costruttori non JSON per i nodi NodeModel. I costruttori JSON vengono richiamati quando si esegue il caricamento da un file e vengono trasferiti ad essi i dati caricati. È tuttavia necessario duplicare un'altra logica utente nel costruttore JSON (ad esempio, inizializzando i gestori eventi per il nodo o l'associazione).
Sono disponibili esempi nel repository DynamoSamples - > ButtonCustomNodeModel, DropDown o SliderCustomNodeModel.
Proprietà pubbliche e serializzazione
In precedenza, uno sviluppatore poteva serializzare e deserializzare dati specifici del modello nel documento XML mediante i metodi SerializeCore
e DeserializeCore
. Questi metodi esistono ancora nell'API, ma verranno dichiarati obsoleti in una release futura di Dynamo (un esempio è disponibile qui). Con l'implementazione JSON.NET ora è possibile serializzare direttamente le proprietà public
della classe derivata da NodeModel nel file .dyn. JSON.net fornisce più attributi per controllare la modalità di serializzazione della proprietà.
Questo esempio che specifica PropertyName
è disponibile qui nel repository di Dynamo.
[JsonProperty(PropertyName = "InputValue")]
public DSColor DsColor {...
Convertitori:
Nota
Se si crea una classe di convertitori JSON.net, Dynamo non dispone attualmente di un meccanismo che consente di inserirla nei metodi di caricamento e salvataggio. Pertanto, anche se si contrassegna la classe con l'attributo [JsonConverter]
, potrebbe non essere utilizzata; è invece possibile chiamare il convertitore direttamente nel setter o nel getter. //TODO need confirmation of this limitation. Any evidence is welcome.
Un esempio che specifica un metodo di serializzazione per convertire la proprietà in una stringa è disponibile qui nel repository di Dynamo.
[JsonProperty("MeasurementType"), JsonConverter(typeof(StringEnumConverter))]
public ConversionMetricUnit SelectedMetricConversion{...
Esclusione delle proprietà
Alle proprietà public
non destinate alla serializzazione è necessario aggiungere l'attributo [JsonIgnore]
. Quando i nodi vengono salvati nel file .dyn, questo assicura che i dati vengano ignorati dal meccanismo di serializzazione e non provochino conseguenze impreviste quando il grafico viene aperto di nuovo. Un esempio di questo è disponibile qui nel repository di Dynamo.
Annullamento/Ripetizione
Come indicato sopra, in passato sono stati utilizzati metodi SerializeCore
e DeserializeCore
per salvare e caricare i nodi nel file .dyn del documento XML. Inoltre, sono stati utilizzati per salvare e caricare lo stato del nodo per l'annullamento/la ripetizione e lo sono ancora. Se si desidera implementare funzionalità complesse di annullamento/ripetizione per il nodo NodeModel dell'interfaccia utente, sarà necessario implementare questi metodi e serializzarli nell'oggetto documento XML fornito come parametro per questi metodi. Questo dovrebbe essere un caso di utilizzo raro, ad eccezione dei nodi complessi dell'interfaccia utente.
API delle porte di input e output
Un'occorrenza comune nei nodi NodeModel interessati dalle modifiche all'API 2.0 è la registrazione della porta nel costruttore del nodo. Esaminando gli esempi nel repository di Dynamo o DynamoSamples, si è notato in precedenza l'uso dei metodi InPortData.Add()
o OutPortData.Add()
. In precedenza, nell'API di Dynamo, le proprietà pubbliche InPortData
e OutPortData
erano contrassegnate come obsolete. Nella versione 2.0 queste proprietà sono state rimosse. Gli sviluppatori dovrebbero ora utilizzare i metodi InPorts.Add()
e OutPorts.Add()
. Inoltre, questi due metodi Add()
hanno firme leggermente diverse:
InPortData.Add(new PortData("Port Name", "Port Description")); //Old version valid in 1.3 but now deprecated
e
InPorts.Add(new PortModel(PortType.Input, this, new PortData("Port Name", "Port Description"))); //Recommended 2.0
Esempi di codice convertito sono disponibili qui nel repository di Dynamo -> DynamoConvert.cs o FileSystem.cs.
L'altro caso di utilizzo comune interessato dalle modifiche all'API 2.0 è correlato ai metodi comunemente usati nel metodo BuildAst()
per determinare il funzionamento del nodo in base alla presenza o all'assenza di connettori di porte. In precedenza veniva utilizzato l'attributo HasConnectedInput(index)
per convalidare lo stato di una porta connessa. Gli sviluppatori dovrebbero ora utilizzare la proprietà InPorts[0].IsConnected
per verificare lo stato di connessione della porta. Un esempio di questo aspetto è disponibile in ColorRange.cs nel repository di Dynamo.
Esempi:
Illustriamo ora l'aggiornamento di un nodo dell'interfaccia utente 1.3 a Dynamo 2.x.
Per caricare e salvare correttamente la classe nodeModel
nella versione 2.0, è sufficiente aggiungere un attributo JsonConstructor per gestire il caricamento delle porte. Trasferire semplicemente le porte al costruttore di base; questa implementazione è vuota.
Nota Non chiamare RegisterPorts()
o qualche variazione di tale valore nell'attributo JsonConstructor: per costruire nuove porte, verranno utilizzati gli attributi dei parametri di input e output nella classe di nodi. Non è questo il caso, poiché si desidera utilizzare le porte caricate che vengono trasferite al costruttore.
Questo esempio aggiunge il costruttore JSON di caricamento minimo possibile. Ma cosa succede se servisse di eseguire una logica di costruzione più complessa, come impostare alcuni listener per la gestione di eventi all'interno del costruttore? L'esempio successivo tratto dal
repository di DynamoSamples è collegato sopra nella JsonConstructors Section
di questo documento.
Di seguito è riportato un costruttore più complesso per un nodo dell'interfaccia utente:
Quando si aggiunge un costruttore JSON per il caricamento di questo nodo da un file, è necessario ricreare una parte di questa logica, ma si noti che non è incluso il codice che crea porte, imposta il collegamento o imposta i valori di default per le proprietà che è possibile caricare dal file.
Notare che altre proprietà pubbliche che sono state serializzate in JSON come ButtonText
e WindowText
non verranno aggiunte come parametri espliciti al costruttore; vengono impostate automaticamente da JSON.net utilizzando i setter per tali proprietà.
Last updated