We can distinguish between a) structured DataTypes that are known at compile time and b) structured DataTypes that are known at runtime.
a) For structured DataTypes that are knwon at compile time you can write a class in C# represting the DataType. This class shall implement the interface IEncodeable. It can get registered at the communication stack. The decoder will directly decode it in this case and you can work with the class. In addition you need to add all required Nodes, including the Encoding nodes and the DataTypeDefinition attribute. If you want to support the DataTypeDictionary you need to add the DataTypeDescription nodes, the DataTypeDictionary and set correct values for these nodes.
The comple work can be done with a few clicks when using UaModeler. So we recommend to use UaModeler for creating the DataTypes and use the generated code. Otherwise you will need to write the code by hand that UaModeler can create for you.
b) For structured DataTypes that are known at runtime, you cannot create a class of course. You can create the DataTypeNodes using the helper functions CreateTypeDictionary and CreateGenericDataType. In this case you can set values using GenericStructureValue
Alternatively you can create the structure DataType using the helper function CreateGenericStructure and set values with GenericEncodeableStructure.