internal override void Decode(EpicsChannel channel, uint nbElements)
        {
            Status   = (Status)channel.DecodeData <ushort>(1, 0);
            Severity = (Severity)channel.DecodeData <ushort>(1, 2);
            int  pos = 4;
            Type t   = typeof(TType);

            if (t.IsArray)
            {
                t = t.GetElementType();
            }
            if (t == typeof(object))
            {
                t = channel.ChannelDefinedType;
            }
            if (t == typeof(double) || t == typeof(float))
            {
                Precision = channel.DecodeData <short>(1, pos);
                pos      += 4; // 2 for precision field + 2 padding for "RISC alignment"
            }
            if (t != typeof(string))
            {
                EGU  = channel.DecodeData <string>(1, pos, 8);
                pos += 8;
                int tSize = TypeHandling.EpicsSize(t);

                //HighDisplayLimit = channel.DecodeData<TType>(1, pos);
                HighDisplayLimit = Convert.ToDouble(channel.DecodeData(t, 1, pos));
                pos += tSize;
                //LowDisplayLimit = channel.DecodeData<TType>(1, pos);
                LowDisplayLimit = Convert.ToDouble(channel.DecodeData(t, 1, pos));
                pos            += tSize;
                //HighAlertLimit = channel.DecodeData<TType>(1, pos);
                HighAlertLimit = Convert.ToDouble(channel.DecodeData(t, 1, pos));
                pos           += tSize;
                //HighWarnLimit = channel.DecodeData<TType>(1, pos);
                HighWarnLimit = Convert.ToDouble(channel.DecodeData(t, 1, pos));
                pos          += tSize;
                //LowWarnLimit = channel.DecodeData<TType>(1, pos);
                LowWarnLimit = Convert.ToDouble(channel.DecodeData(t, 1, pos));
                pos         += tSize;
                //LowAlertLimit = channel.DecodeData<TType>(1, pos);
                LowAlertLimit   = Convert.ToDouble(channel.DecodeData(t, 1, pos));
                pos            += tSize;
                LowControlLimit = Convert.ToDouble(channel.DecodeData(t, 1, pos));
                pos            += tSize;
                //HighControlLimit = channel.DecodeData<TType>(1, pos);
                HighControlLimit = Convert.ToDouble(channel.DecodeData(t, 1, pos));
                pos += tSize;
            }
            else
            {
                EGU = "";
            }
            if (t == typeof(byte))
            {
                pos++; // 1 padding for "RISC alignment"
            }
            Value = channel.DecodeData <TType>(nbElements, pos);
        }
        internal EpicsChannel(EpicsClient client, string channelName)
        {
            this.ChannelName = channelName;
            this.Status      = ChannelStatus.REQUESTED;
            this.Client      = client;
            MonitorMask      = MonitorMask.VALUE;
            HasValue         = false;

            SearchPacket            = DataPacket.Create(16 + ChannelName.Length + TypeHandling.Padding(ChannelName.Length));
            SearchPacket.Command    = (ushort)CommandID.CA_PROTO_SEARCH;
            SearchPacket.DataType   = (ushort)EpicsConstants.DONT_REPLY;
            SearchPacket.DataCount  = (ushort)EpicsConstants.CA_MINOR_PROTOCOL_REVISION;
            SearchPacket.Parameter1 = cid;
            SearchPacket.Parameter2 = cid;
            SearchPacket.SetDataAsString(ChannelName);
        }
        internal object DecodeData(Type t, uint nbElements = 1, int startPost = 0, int maxSize = 40)
        {
            if (t.IsSubclassOf(typeof(Decodable)) && !t.IsArray)
            {
                Decodable res = (Decodable)t.GetConstructor(System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance, null, new Type[] { }, null).Invoke(new object[] { });
                res.Decode(this, nbElements);
                return(res);
            }

            if (t == typeof(object))
            {
                t = channelDefinedType;
            }

            Type baseT = t;

            if (baseT.IsArray)
            {
                baseT = t.GetElementType();
            }

            if (t.IsArray)
            {
                Type dl      = typeof(List <>);
                Type genList = dl.MakeGenericType(new Type[] { baseT });

                System.Collections.IList res = (System.Collections.IList)Activator.CreateInstance(genList);

                int pos         = (int)RawData.HeaderSize + startPost;
                int elementSize = TypeHandling.EpicsSize(baseT);
                for (int i = 0; i < nbElements; i++)
                {
                    switch (TypeHandling.Lookup[baseT])
                    {
                    case EpicsType.Int:
                        res.Add(RawData.GetInt32(pos));
                        break;

                    case EpicsType.Short:
                        res.Add(RawData.GetInt16(pos));
                        break;

                    case EpicsType.Float:
                        res.Add(RawData.GetFloat(pos));
                        break;

                    case EpicsType.Double:
                        res.Add(RawData.GetDouble(pos));
                        break;

                    case EpicsType.Byte:
                        res.Add(RawData.GetByte(pos));
                        break;

                    default:
                        throw new Exception("Type not supported");
                    }
                    pos += elementSize;
                }
                return(((dynamic)res).ToArray());
            }

            if (baseT == typeof(DateTime))
            {
                long     secs     = RawData.GetUInt32((int)RawData.HeaderSize + startPost);
                long     nanoSecs = RawData.GetUInt32((int)RawData.HeaderSize + startPost + 4);
                DateTime d        = (new DateTime(timestampBase.Ticks + (secs * 10000000L) + (nanoSecs / 100L))).ToLocalTime();
                return(d);
            }

            switch (TypeHandling.Lookup[baseT])
            {
            case EpicsType.Internal_UInt:
                return(RawData.GetUInt32((int)RawData.HeaderSize + startPost));

            case EpicsType.Internal_UShort:
                return(RawData.GetUInt16((int)RawData.HeaderSize + startPost));

            case EpicsType.Int:
                return(RawData.GetInt32((int)RawData.HeaderSize + startPost));

            case EpicsType.Short:
                return(RawData.GetInt16((int)RawData.HeaderSize + startPost));

            case EpicsType.Float:
                return(RawData.GetFloat((int)RawData.HeaderSize + startPost));

            case EpicsType.Double:
                return(RawData.GetDouble((int)RawData.HeaderSize + startPost));

            case EpicsType.String:
                return(RawData.GetDataAsString(startPost, maxSize));

            case EpicsType.Byte:
                return(RawData.GetByte((int)RawData.HeaderSize + startPost));

            default:
                //throw new Exception("Type not supported");
                return(new object());
            }
        }
        protected DataPacket WritePacket <TType>(TType newValue)
        {
            int  headerSize = 16;
            uint nbElem     = 1;

            if (newValue is IEnumerable <object> )
            {
                nbElem = (uint)((IEnumerable <object>)newValue).Count();
            }
            Type t = typeof(TType);

            if (t.IsArray)
            {
                nbElem = (uint)((Array)((object)newValue)).Length;
                // if too many array elements, use extended header
                if (nbElem > 0xffff)
                {
                    headerSize = 24;
                }
                t = t.GetElementType();
            }
            else if (t.IsGenericType)
            {
                if (t.GetGenericArguments().First() == typeof(object))
                {
                    t = t.GetGenericTypeDefinition().MakeGenericType(new Type[] { channelDefinedType });
                }
            }
            if (t == typeof(object))
            {
                t = channelDefinedType;
            }

            int payloadSize = (int)(nbElem * TypeHandling.EpicsSize(t));

            if (payloadSize % 8 > 0)
            {
                payloadSize += 8 - (payloadSize % 8);
            }
            // if payload too large, use extended header
            if (payloadSize > 0x4000)
            {
                headerSize = 24;
            }
            DataPacket packet = DataPacket.Create(headerSize + payloadSize);

            packet.Command    = (ushort)CommandID.CA_PROTO_WRITE_NOTIFY;
            packet.DataCount  = nbElem;
            packet.DataType   = (ushort)TypeHandling.Lookup[t];
            packet.Parameter1 = SID;
            uint ioid = (NextIoId++);

            packet.Parameter2 = ioid;

            if (nbElem > 1)
            {
                int pos         = headerSize;
                int elementSize = TypeHandling.EpicsSize(t);
                foreach (var elem in (System.Collections.IEnumerable)newValue)
                {
                    switch (TypeHandling.Lookup[t])
                    {
                    case EpicsType.Int:
                        packet.SetInt32(pos, (int)elem);
                        break;

                    case EpicsType.Short:
                        packet.SetInt16(pos, (short)elem);
                        break;

                    case EpicsType.Float:
                        packet.SetFloat(pos, (float)elem);
                        break;

                    case EpicsType.Double:
                        packet.SetDouble(pos, (double)elem);
                        break;

                    case EpicsType.Byte:
                        packet.SetByte(pos, (byte)elem);
                        break;

                    default:
                        throw new Exception("Type not supported");
                    }
                    pos += elementSize;
                }
            }
            else
            {
                switch (TypeHandling.Lookup[t])
                {
                case EpicsType.Int:
                    packet.SetInt32((int)packet.HeaderSize, (int)(object)newValue);
                    break;

                case EpicsType.Short:
                    packet.SetInt16((int)packet.HeaderSize, (short)(object)newValue);
                    break;

                case EpicsType.Float:
                    packet.SetFloat((int)packet.HeaderSize, (float)(object)newValue);
                    break;

                case EpicsType.Double:
                    packet.SetDouble((int)packet.HeaderSize, (double)(object)newValue);
                    break;

                case EpicsType.String:
                    packet.SetDataAsString((string)(object)newValue);
                    break;

                case EpicsType.Byte:
                    packet.SetByte((int)packet.HeaderSize, (byte)(object)newValue);
                    break;

                default:
                    throw new Exception("Type not currently supported.");
                }
            }

            return(packet);
        }