/// <summary>
        /// Lookup read/write actions for the given type.
        /// </summary>
        /// <param name="field">The field.</param>
        /// <param name="writeAction">Write action.</param>
        /// <param name="readAction">Read action.</param>
        public static void TypeActions(FieldInfo field, out PortableReflectiveWriteAction writeAction,
                                       out PortableReflectiveReadAction readAction)
        {
            var type = field.FieldType;

            if (type.IsPrimitive)
            {
                HandlePrimitive(field, out writeAction, out readAction);
            }
            else if (type.IsArray)
            {
                HandleArray(field, out writeAction, out readAction);
            }
            else
            {
                HandleOther(field, out writeAction, out readAction);
            }
        }
        /// <summary>
        /// Handle array type.
        /// </summary>
        /// <param name="field">The field.</param>
        /// <param name="writeAction">Write action.</param>
        /// <param name="readAction">Read action.</param>
        private static void HandleArray(FieldInfo field, out PortableReflectiveWriteAction writeAction,
                                        out PortableReflectiveReadAction readAction)
        {
            Type elemType = field.FieldType.GetElementType();

            if (elemType == typeof(bool))
            {
                writeAction = GetWriter <bool[]>(field, (f, w, o) => w.WriteBooleanArray(f, o));
                readAction  = GetReader(field, (f, r) => r.ReadBooleanArray(f));
            }
            else if (elemType == typeof(byte))
            {
                writeAction = GetWriter <byte[]>(field, (f, w, o) => w.WriteByteArray(f, o));
                readAction  = GetReader(field, (f, r) => r.ReadByteArray(f));
            }
            else if (elemType == typeof(sbyte))
            {
                writeAction = GetWriter <sbyte[]>(field, (f, w, o) => w.WriteByteArray(f, (byte[])(Array)o));
                readAction  = GetReader(field, (f, r) => (sbyte[])(Array)r.ReadByteArray(f));
            }
            else if (elemType == typeof(short))
            {
                writeAction = GetWriter <short[]>(field, (f, w, o) => w.WriteShortArray(f, o));
                readAction  = GetReader(field, (f, r) => r.ReadShortArray(f));
            }
            else if (elemType == typeof(ushort))
            {
                writeAction = GetWriter <ushort[]>(field, (f, w, o) => w.WriteShortArray(f, (short[])(Array)o));
                readAction  = GetReader(field, (f, r) => (ushort[])(Array)r.ReadShortArray(f));
            }
            else if (elemType == typeof(char))
            {
                writeAction = GetWriter <char[]>(field, (f, w, o) => w.WriteCharArray(f, o));
                readAction  = GetReader(field, (f, r) => r.ReadCharArray(f));
            }
            else if (elemType == typeof(int))
            {
                writeAction = GetWriter <int[]>(field, (f, w, o) => w.WriteIntArray(f, o));
                readAction  = GetReader(field, (f, r) => r.ReadIntArray(f));
            }
            else if (elemType == typeof(uint))
            {
                writeAction = GetWriter <uint[]>(field, (f, w, o) => w.WriteIntArray(f, (int[])(Array)o));
                readAction  = GetReader(field, (f, r) => (uint[])(Array)r.ReadIntArray(f));
            }
            else if (elemType == typeof(long))
            {
                writeAction = GetWriter <long[]>(field, (f, w, o) => w.WriteLongArray(f, o));
                readAction  = GetReader(field, (f, r) => r.ReadLongArray(f));
            }
            else if (elemType == typeof(ulong))
            {
                writeAction = GetWriter <ulong[]>(field, (f, w, o) => w.WriteLongArray(f, (long[])(Array)o));
                readAction  = GetReader(field, (f, r) => (ulong[])(Array)r.ReadLongArray(f));
            }
            else if (elemType == typeof(float))
            {
                writeAction = GetWriter <float[]>(field, (f, w, o) => w.WriteFloatArray(f, o));
                readAction  = GetReader(field, (f, r) => r.ReadFloatArray(f));
            }
            else if (elemType == typeof(double))
            {
                writeAction = GetWriter <double[]>(field, (f, w, o) => w.WriteDoubleArray(f, o));
                readAction  = GetReader(field, (f, r) => r.ReadDoubleArray(f));
            }
            else if (elemType == typeof(decimal))
            {
                writeAction = GetWriter <decimal[]>(field, (f, w, o) => w.WriteDecimalArray(f, o));
                readAction  = GetReader(field, (f, r) => r.ReadDecimalArray(f));
            }
            else if (elemType == typeof(string))
            {
                writeAction = GetWriter <string[]>(field, (f, w, o) => w.WriteStringArray(f, o));
                readAction  = GetReader(field, (f, r) => r.ReadStringArray(f));
            }
            else if (elemType == typeof(Guid?))
            {
                writeAction = GetWriter <Guid?[]>(field, (f, w, o) => w.WriteGuidArray(f, o));
                readAction  = GetReader(field, (f, r) => r.ReadGuidArray(f));
            }
            else if (elemType == typeof(DateTime?))
            {
                writeAction = GetWriter <DateTime?[]>(field, (f, w, o) => w.WriteDateArray(f, o));
                readAction  = GetReader(field, (f, r) => r.ReadDateArray(f));
            }
            else if (elemType.IsEnum)
            {
                writeAction = GetWriter(field, MthdWriteEnumArray, elemType);
                readAction  = GetReader(field, MthdReadEnumArray, elemType);
            }
            else
            {
                writeAction = GetWriter(field, MthdWriteObjArray, elemType);
                readAction  = GetReader(field, MthdReadObjArray, elemType);
            }
        }
        /// <summary>
        /// Handle other type.
        /// </summary>
        /// <param name="field">The field.</param>
        /// <param name="writeAction">Write action.</param>
        /// <param name="readAction">Read action.</param>
        private static void HandleOther(FieldInfo field, out PortableReflectiveWriteAction writeAction,
                                        out PortableReflectiveReadAction readAction)
        {
            var type = field.FieldType;

            var genericDef = type.IsGenericType ? type.GetGenericTypeDefinition() : null;

            bool nullable = genericDef == typeof(Nullable <>);

            var nullableType = nullable ? type.GetGenericArguments()[0] : null;

            if (type == typeof(decimal))
            {
                writeAction = GetWriter <decimal>(field, (f, w, o) => w.WriteDecimal(f, o));
                readAction  = GetReader(field, (f, r) => r.ReadDecimal(f));
            }
            else if (type == typeof(string))
            {
                writeAction = GetWriter <string>(field, (f, w, o) => w.WriteString(f, o));
                readAction  = GetReader(field, (f, r) => r.ReadString(f));
            }
            else if (type == typeof(Guid))
            {
                writeAction = GetWriter <Guid>(field, (f, w, o) => w.WriteGuid(f, o));
                readAction  = GetReader(field, (f, r) => r.ReadGuid(f) ?? default(Guid));
            }
            else if (nullable && nullableType == typeof(Guid))
            {
                writeAction = GetWriter <Guid?>(field, (f, w, o) => w.WriteGuid(f, o));
                readAction  = GetReader(field, (f, r) => r.ReadGuid(f));
            }
            else if (type == typeof(DateTime))
            {
                writeAction = GetWriter <DateTime>(field, (f, w, o) => w.WriteDate(f, o));
                readAction  = GetReader(field, (f, r) => r.ReadDate(f) ?? default(DateTime));
            }
            else if (nullable && nullableType == typeof(DateTime))
            {
                writeAction = GetWriter <DateTime?>(field, (f, w, o) => w.WriteDate(f, o));
                readAction  = GetReader(field, (f, r) => r.ReadDate(f));
            }
            else if (type.IsEnum)
            {
                writeAction = GetWriter <object>(field, (f, w, o) => w.WriteEnum(f, o), true);
                readAction  = GetReader(field, MthdReadEnum);
            }
            else if (genericDef == PortableUtils.TypGenericDictionary ||
                     type.GetInterface(PortableUtils.TypGenericDictionary.FullName) != null)
            {
                writeAction = GetWriter(field, MthdWriteGenericDictionary, type.GetGenericArguments());
                readAction  = GetReader(field, MthdReadGenericDictionary, type.GetGenericArguments());
            }
            else if (genericDef == PortableUtils.TypGenericCollection ||
                     type.GetInterface(PortableUtils.TypGenericCollection.FullName) != null)
            {
                writeAction = GetWriter(field, MthdWriteGenericCollection, type.GetGenericArguments());
                readAction  = GetReader(field, MthdReadGenericCollection, type.GetGenericArguments());
            }
            else if (type == PortableUtils.TypDictionary || type.GetInterface(PortableUtils.TypDictionary.FullName) != null)
            {
                writeAction = GetWriter <IDictionary>(field, (f, w, o) => w.WriteDictionary(f, o));
                readAction  = GetReader(field, (f, r) => r.ReadDictionary(f));
            }
            else if (type == PortableUtils.TypCollection || type.GetInterface(PortableUtils.TypCollection.FullName) != null)
            {
                writeAction = GetWriter <ICollection>(field, (f, w, o) => w.WriteCollection(f, o));
                readAction  = GetReader(field, (f, r) => r.ReadCollection(f));
            }
            else
            {
                writeAction = GetWriter(field, MthdWriteObj);
                readAction  = GetReader(field, MthdReadObj);
            }
        }
        /// <summary>
        /// Handle primitive type.
        /// </summary>
        /// <param name="field">The field.</param>
        /// <param name="writeAction">Write action.</param>
        /// <param name="readAction">Read action.</param>
        /// <exception cref="IgniteException">Unsupported primitive type:  + type.Name</exception>
        private static void HandlePrimitive(FieldInfo field, out PortableReflectiveWriteAction writeAction,
                                            out PortableReflectiveReadAction readAction)
        {
            var type = field.FieldType;

            if (type == typeof(bool))
            {
                writeAction = GetWriter <bool>(field, (f, w, o) => w.WriteBoolean(f, o));
                readAction  = GetReader(field, (f, r) => r.ReadBoolean(f));
            }
            else if (type == typeof(sbyte))
            {
                writeAction = GetWriter <sbyte>(field, (f, w, o) => w.WriteByte(f, unchecked ((byte)o)));
                readAction  = GetReader(field, (f, r) => unchecked ((sbyte)r.ReadByte(f)));
            }
            else if (type == typeof(byte))
            {
                writeAction = GetWriter <byte>(field, (f, w, o) => w.WriteByte(f, o));
                readAction  = GetReader(field, (f, r) => r.ReadByte(f));
            }
            else if (type == typeof(short))
            {
                writeAction = GetWriter <short>(field, (f, w, o) => w.WriteShort(f, o));
                readAction  = GetReader(field, (f, r) => r.ReadShort(f));
            }
            else if (type == typeof(ushort))
            {
                writeAction = GetWriter <ushort>(field, (f, w, o) => w.WriteShort(f, unchecked ((short)o)));
                readAction  = GetReader(field, (f, r) => unchecked ((ushort)r.ReadShort(f)));
            }
            else if (type == typeof(char))
            {
                writeAction = GetWriter <char>(field, (f, w, o) => w.WriteChar(f, o));
                readAction  = GetReader(field, (f, r) => r.ReadChar(f));
            }
            else if (type == typeof(int))
            {
                writeAction = GetWriter <int>(field, (f, w, o) => w.WriteInt(f, o));
                readAction  = GetReader(field, (f, r) => r.ReadInt(f));
            }
            else if (type == typeof(uint))
            {
                writeAction = GetWriter <uint>(field, (f, w, o) => w.WriteInt(f, unchecked ((int)o)));
                readAction  = GetReader(field, (f, r) => unchecked ((uint)r.ReadInt(f)));
            }
            else if (type == typeof(long))
            {
                writeAction = GetWriter <long>(field, (f, w, o) => w.WriteLong(f, o));
                readAction  = GetReader(field, (f, r) => r.ReadLong(f));
            }
            else if (type == typeof(ulong))
            {
                writeAction = GetWriter <ulong>(field, (f, w, o) => w.WriteLong(f, unchecked ((long)o)));
                readAction  = GetReader(field, (f, r) => unchecked ((ulong)r.ReadLong(f)));
            }
            else if (type == typeof(float))
            {
                writeAction = GetWriter <float>(field, (f, w, o) => w.WriteFloat(f, o));
                readAction  = GetReader(field, (f, r) => r.ReadFloat(f));
            }
            else if (type == typeof(double))
            {
                writeAction = GetWriter <double>(field, (f, w, o) => w.WriteDouble(f, o));
                readAction  = GetReader(field, (f, r) => r.ReadDouble(f));
            }
            else
            {
                throw new IgniteException("Unsupported primitive type: " + type.Name);
            }
        }