Questo documento illustra come è possibile creare dei tipi di dato personalizzati e utilizzarli nello scambio dati dei driver iTools®. Ogni driver è in grado di gestire i propri tipi di dato nativi come possono essere ad esempio gli interi, reali, byte, stringhe, ecc…, così da poter definire delle Variable con VariableType impostato su uno dei tipi gestiti dal driver:
Variable.VariableType = “Integer”;
A volte vi è la necessità di utilizzare tipi di dato aggiuntivi ad esempio nel caso in cui sul protocollo nativo sia stato implementato un “dialetto” al fine di facilitare lettura impostazione delle informazioni da scambiare, sicuramente queste procedure non sono vincolanti, in quanto vi possono essere diverse alternative per gestire situazioni in cui le informazioni da scambiare non rispettano gli standard imposti dalle specifiche del protocollo di comunicazione, però facilitano molto lo sviluppo del processo applicativo che implementa le funzionalità richieste dall’utente. Attraverso questa nuova caratteristica presente a partire dalla versione 3.3 del framework IToolS è possibile inserire nel codice utente implementazioni personalizzate dei tipi di dato gestiti dal driver in grado di contenere informazioni che per loro natura non potrebbero essere inserite nei tipi di dato predefiniti. Come esempio si potrebbe prendere in considerazione la rappresentazione di un dato che a parità di informazione può avere rappresentazione differenti, si pensi alle stringhe in formato ascii o unicode, l’ordinamento dei byte o delle word che possono comporre un numero reale (a parità di informazione corrisponde una rappresentazione differente e quindi un numero differente), oppure potremmo avere la necessità di gestire dati complessi che sono l’unione di più dati elementari. Grazie a questa opzione è possibile scrivere il proprio tipo di dato e darlo in gestione al driver che lo tratta allo stesso modo dei tipi in esso nativi, questo vuol dire che come gli altri tipi sarà soggetto a ottimizzazione sia in lettura che in scrittura e comunque come previsto dall’implementazione del driver in questione.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 |
#region MyPoint /// <summary> /// Classe che definisce il tipo MyPoint /// </summary> [IToolS.IOServerTypeName(MY_POINT)] [Serializable] public class MyPoint : IToolS.Data.TypeBase { public struct CustomPoint { private int m_x; private int m_y; public CustomPoint(int x, int y) { m_x = x; m_y = y; } public int X { get { return m_x; } set { m_x = value; } } public int Y { get { return m_y; } set { m_y = value; } } public static implicit operator String(CustomPoint point) { return String.Join(",", new String[] { point.X.ToString(), point.Y.ToString() }); } public static implicit operator CustomPoint(String stringPoint) { String[] splitPoint = stringPoint.Split(','); return new CustomPoint(Int32.Parse(splitPoint[0]), Int32.Parse(splitPoint[1])); } public override string ToString() { return String.Join(",", new String[] { X.ToString(), Y.ToString() }); } } #region Fields public const String MY_POINT = "MyPoint"; #endregion #region MyPoint /// <summary> /// Inizializza una nuova istanza della classe MyPoint /// </summary> /// <param name="variable">Variabile in cui inserire il tipo richiesto</param> public MyPoint(IToolS.Data.IVariableInternal variable) : base(variable) { } #endregion #region Conversions /// <summary> /// Ritorna il valore scalato della variabile /// </summary> /// <param name="value">Valore da scalare</param> /// <returns>Valore scalato</returns> public override object GetScaled(object value) { return value; } /// <summary> /// Ritorna il valore non scalato del valore passato /// </summary> /// <param name="value">Valore da de-scalare</param> /// <returns>Valore de-scalato della variabile</returns> public override object GetUnScaled(object value) { return value; } /// <summary> /// Ritorna il valore convertito della variabile /// </summary> /// <param name="value">Valore da scalare</param> /// <returns>Valore convertito</returns> public override object GetConverted(object value) { return value; } /// <summary> /// Ritorna il valore de-convertito della variabile /// </summary> /// <param name="value">Valore da de-convertire</param> /// <returns>Valore de-convertito della variabile</returns> public override object GetUnconverted(object value) { return value; } #endregion #region GetMaxValue /// <summary> /// Ritorna il massimo valore della variabile /// </summary> /// <returns>Massimo valore della variabile</returns> public override Object GetMaxValue() { return new CustomPoint(Int32.MaxValue, Int32.MaxValue); } #endregion #region GetMinValue /// <summary> /// Ritorna il minimo valore della variabile /// </summary> /// <returns>Minimo valore della variabile</returns> public override Object GetMinValue() { return new CustomPoint(Int32.MinValue, Int32.MinValue); } #endregion #region GetBytes /// <summary> /// Ottiene la rappresentazione in byte del valore passato per paramtro /// </summary> /// <param name="value">Valore di convertire i byte</param> /// <returns>Byte del valore passato per parametro</returns> public override Byte[] GetBytes(Object value) { CustomPoint point; if (value is CustomPoint) { point = (CustomPoint)value; } else if (value is String) { point = Convert.ToString(value); } else { throw new IToolS.Base.IToolSException("Unhandled type conversion"); } Byte[] byteX = BitConverter.GetBytes(point.X); Byte[] byteY = BitConverter.GetBytes(point.Y); return new Byte[] { byteX[0], byteX[1], byteX[2], byteX[3], byteY[0], byteY[1], byteY[2], byteY[3] }; } #endregion #region GetValue /// <summary> /// Imposta il valore della variabile attraverso i byte passati per parametro /// </summary> /// <param name="bytes">Byte che definiscono i valore della variabile</param> /// <returns>Valore della variabile</returns> public override Object GetValue(Byte[] bytes) { if (bytes == null) return null; return new CustomPoint(BitConverter.ToInt32(bytes, 0), BitConverter.ToInt32(bytes, 4)); } #endregion #region GetTargetState /// <summary> /// Ritorna un valore che indica se il target è stato raggiunto o fallito /// </summary> /// <param name="variable">Variabile contenente i target</param> /// <param name="target">Target da controllare</param> /// <param name="value">Valore della variabile associata al target</param> /// <returns>1 se il target è stato raggiunto, -1 se il target è fallito</returns> protected override int GetTargetState(IToolS.Data.IVariableInternal variable, IToolS.Data.VariableTarget target, object value) { CustomPoint pt = (CustomPoint)value; if (pt.ToString() == Convert.ToString(target.LowerValue) && pt.ToString() == Convert.ToString(target.UpperValue)) return IToolS.Data.VariableTarget.REACHED; return IToolS.Data.VariableTarget.FAILED; } #endregion #region DotNetType /// <summary> /// Ottiene il tipo .net corrispondente /// </summary> public override Type DotNetType { get { return typeof(CustomPoint); } } #endregion #region FootprintAddresses /// <summary> /// Ottiene il numero di byte occupati da questo tipo /// </summary> public override int FootprintAddresses { get { return 8 / (int)Variable.AddressSize; } } #endregion } #endregion |