Пример #1
0
        /// <summary>
        /// Gets the reader with a specified generic method.
        /// </summary>
        private static BinaryReflectiveReadAction GetReader0(FieldInfo field, MethodInfo method, bool raw,
                                                             params Type[] genericArgs)
        {
            Debug.Assert(field != null);
            Debug.Assert(field.DeclaringType != null);   // non-static

            if (genericArgs.Length == 0)
            {
                genericArgs = new[] { field.FieldType }
            }
            ;

            // Call Reader method
            var        readerParam = Expression.Parameter(typeof(IBinaryReader));
            var        readMethod  = method.MakeGenericMethod(genericArgs);
            Expression readExpr    = raw
                ? Expression.Call(Expression.Call(readerParam, MthdGetRawReader), readMethod)
                : Expression.Call(readerParam, readMethod, Expression.Constant(BinaryUtils.CleanFieldName(field.Name)));

            if (readMethod.ReturnType != field.FieldType)
            {
                readExpr = Expression.Convert(readExpr, field.FieldType);
            }

            // Assign field value
            var targetParam          = Expression.Parameter(typeof(object));
            var targetParamConverted = Expression.Convert(targetParam, typeof(object));
            var assignExpr           = Expression.Call(DelegateConverter.GetWriteFieldMethod(field), targetParamConverted,
                                                       readExpr);

            // Compile and return
            return(Expression.Lambda <BinaryReflectiveReadAction>(assignExpr, targetParam, readerParam).Compile());
        }
    }
Пример #2
0
        /// <summary>
        /// Gets the reader with a specified write action.
        /// </summary>
        private static BinaryReflectiveWriteAction GetWriter <T>(FieldInfo field,
                                                                 Expression <Action <string, IBinaryWriter, T> > write)
        {
            Debug.Assert(field != null);
            Debug.Assert(field.DeclaringType != null);   // non-static
            Debug.Assert(write != null);

            // Get field value
            var        targetParam          = Expression.Parameter(typeof(object));
            var        targetParamConverted = Expression.Convert(targetParam, field.DeclaringType);
            Expression fldExpr = Expression.Field(targetParamConverted, field);

            if (field.FieldType != typeof(T))
            {
                fldExpr = Expression.Convert(fldExpr, typeof(T));
            }

            // Call Writer method
            var writerParam  = Expression.Parameter(typeof(IBinaryWriter));
            var fldNameParam = Expression.Constant(BinaryUtils.CleanFieldName(field.Name));
            var writeExpr    = Expression.Invoke(write, fldNameParam, writerParam, fldExpr);

            // Compile and return
            return(Expression.Lambda <BinaryReflectiveWriteAction>(writeExpr, targetParam, writerParam).Compile());
        }
Пример #3
0
        /// <summary>
        /// Gets the writer with a specified generic method.
        /// </summary>
        private static BinaryReflectiveWriteAction GetWriter0(FieldInfo field, MethodInfo method, bool raw,
                                                              params Type[] genericArgs)
        {
            Debug.Assert(field != null);
            Debug.Assert(field.DeclaringType != null);   // non-static
            Debug.Assert(method != null);

            if (genericArgs.Length == 0)
            {
                genericArgs = new[] { field.FieldType }
            }
            ;

            // Get field value
            var targetParam          = Expression.Parameter(typeof(object));
            var targetParamConverted = Expression.Convert(targetParam, field.DeclaringType);
            var fldExpr = Expression.Field(targetParamConverted, field);

            // Call Writer method
            var writerParam = Expression.Parameter(typeof(IBinaryWriter));

            var writeMethod = method.MakeGenericMethod(genericArgs);

            var writeExpr = raw
                ? Expression.Call(Expression.Call(writerParam, MthdGetRawWriter), writeMethod, fldExpr)
                : Expression.Call(writerParam, writeMethod, Expression.Constant(BinaryUtils.CleanFieldName(field.Name)),
                                  fldExpr);

            // Compile and return
            return(Expression.Lambda <BinaryReflectiveWriteAction>(writeExpr, targetParam, writerParam).Compile());
        }
Пример #4
0
        /// <summary>
        /// Compare two FieldInfo instances.
        /// </summary>
        private static int Compare(FieldInfo info1, FieldInfo info2)
        {
            string name1 = BinaryUtils.CleanFieldName(info1.Name);
            string name2 = BinaryUtils.CleanFieldName(info2.Name);

            return(string.Compare(name1, name2, StringComparison.OrdinalIgnoreCase));
        }
Пример #5
0
        /// <summary>
        /// Gets the reader with a specified read action.
        /// </summary>
        private static BinaryReflectiveReadAction GetReader <T>(FieldInfo field,
                                                                Expression <Func <string, IBinaryReader, T> > read)
        {
            Debug.Assert(field != null);
            Debug.Assert(field.DeclaringType != null);   // non-static

            // Call Reader method
            var        readerParam  = Expression.Parameter(typeof(IBinaryReader));
            var        fldNameParam = Expression.Constant(BinaryUtils.CleanFieldName(field.Name));
            Expression readExpr     = Expression.Invoke(read, fldNameParam, readerParam);

            if (typeof(T) != field.FieldType)
            {
                readExpr = Expression.Convert(readExpr, field.FieldType);
            }

            // Assign field value
            var targetParam          = Expression.Parameter(typeof(object));
            var targetParamConverted = Expression.Convert(targetParam, field.DeclaringType);
            var assignExpr           = Expression.Call(DelegateConverter.GetWriteFieldMethod(field), targetParamConverted,
                                                       readExpr);

            // Compile and return
            return(Expression.Lambda <BinaryReflectiveReadAction>(assignExpr, targetParam, readerParam).Compile());
        }
        /// <summary>Register type.</summary>
        /// <param name="type">Type.</param>
        /// <param name="typeId">Type ID.</param>
        /// <param name="converter">Name converter.</param>
        /// <param name="idMapper">ID mapper.</param>
        internal BinaryReflectiveSerializerInternal Register(Type type, int typeId, IBinaryNameMapper converter,
                                                             IBinaryIdMapper idMapper)
        {
            Debug.Assert(_wActions == null && _rActions == null);

            List <FieldInfo> fields = new List <FieldInfo>();

            Type curType = type;

            while (curType != null)
            {
                foreach (FieldInfo field in curType.GetFields(Flags))
                {
                    if (!field.IsNotSerialized)
                    {
                        fields.Add(field);
                    }
                }

                curType = curType.BaseType;
            }

            IDictionary <int, string> idMap = new Dictionary <int, string>();

            foreach (FieldInfo field in fields)
            {
                string fieldName = BinaryUtils.CleanFieldName(field.Name);

                int fieldId = BinaryUtils.FieldId(typeId, fieldName, converter, idMapper);

                if (idMap.ContainsKey(fieldId))
                {
                    throw new BinaryObjectException("Conflicting field IDs [type=" +
                                                    type.Name + ", field1=" + idMap[fieldId] + ", field2=" + fieldName +
                                                    ", fieldId=" + fieldId + ']');
                }

                idMap[fieldId] = fieldName;
            }

            fields.Sort(Compare);

            var wActions = new BinaryReflectiveWriteAction[fields.Count];
            var rActions = new BinaryReflectiveReadAction[fields.Count];

            for (int i = 0; i < fields.Count; i++)
            {
                BinaryReflectiveWriteAction writeAction;
                BinaryReflectiveReadAction  readAction;

                BinaryReflectiveActions.GetTypeActions(fields[i], out writeAction, out readAction, _rawMode);

                wActions[i] = writeAction;
                rActions[i] = readAction;
            }

            return(new BinaryReflectiveSerializerInternal(wActions, rActions, _rawMode));
        }
Пример #7
0
        /// <summary>
        /// Register type.
        /// </summary>
        /// <param name="type">Type.</param>
        /// <param name="typeId">Type ID.</param>
        /// <param name="converter">Name converter.</param>
        /// <param name="idMapper">ID mapper.</param>
        /// <param name="forceTimestamp">Force timestamp serialization for DateTime fields..</param>
        /// <returns>Resulting serializer.</returns>
        internal BinaryReflectiveSerializerInternal Register(Type type, int typeId, IBinaryNameMapper converter,
                                                             IBinaryIdMapper idMapper, bool forceTimestamp)
        {
            Debug.Assert(_wActions == null && _rActions == null);

            var fields = ReflectionUtils.GetAllFields(type).Where(x => !x.IsNotSerialized).ToList();

            IDictionary <int, string> idMap = new Dictionary <int, string>();

            foreach (FieldInfo field in fields)
            {
                string fieldName = BinaryUtils.CleanFieldName(field.Name);

                int fieldId = BinaryUtils.FieldId(typeId, fieldName, converter, idMapper);

                if (idMap.ContainsKey(fieldId))
                {
                    if (fieldName == idMap[fieldId])
                    {
                        string baseClassName = field.DeclaringType != null ? field.DeclaringType.Name : null;
                        throw new BinaryObjectException(string.Format(
                                                            "{0} derives from {1} and hides field {2} from the base class. " +
                                                            "Ignite can not serialize two fields with the same name.", type.Name, baseClassName, fieldName));
                    }

                    throw new BinaryObjectException(string.Format(
                                                        "Conflicting field IDs [type={0}, field1={1}, field2={2}, fieldId={3}])",
                                                        type.Name, idMap[fieldId], fieldName, fieldId));
                }

                idMap[fieldId] = fieldName;
            }

            fields.Sort(Compare);

            var wActions = new BinaryReflectiveWriteAction[fields.Count];
            var rActions = new BinaryReflectiveReadAction[fields.Count];

            for (int i = 0; i < fields.Count; i++)
            {
                BinaryReflectiveWriteAction writeAction;
                BinaryReflectiveReadAction  readAction;

                BinaryReflectiveActions.GetTypeActions(fields[i], out writeAction, out readAction, _rawMode, forceTimestamp);

                wActions[i] = writeAction;
                rActions[i] = readAction;
            }

            var serDesc = SerializableTypeDescriptor.Get(type);

            return(new BinaryReflectiveSerializerInternal(wActions, rActions, _rawMode, serDesc));
        }
Пример #8
0
        /// <summary>Register type.</summary>
        /// <param name="type">Type.</param>
        /// <param name="typeId">Type ID.</param>
        /// <param name="converter">Name converter.</param>
        /// <param name="idMapper">ID mapper.</param>
        public void Register(Type type, int typeId, IBinaryNameMapper converter,
                             IBinaryIdMapper idMapper)
        {
            if (type.GetInterface(typeof(IBinarizable).Name) != null)
            {
                return;
            }

            List <FieldInfo> fields = new List <FieldInfo>();

            Type curType = type;

            while (curType != null)
            {
                foreach (FieldInfo field in curType.GetFields(Flags))
                {
                    if (!field.IsNotSerialized)
                    {
                        fields.Add(field);
                    }
                }

                curType = curType.BaseType;
            }

            IDictionary <int, string> idMap = new Dictionary <int, string>();

            foreach (FieldInfo field in fields)
            {
                string fieldName = BinaryUtils.CleanFieldName(field.Name);

                int fieldId = BinaryUtils.FieldId(typeId, fieldName, converter, idMapper);

                if (idMap.ContainsKey(fieldId))
                {
                    throw new BinaryObjectException("Conflicting field IDs [type=" +
                                                    type.Name + ", field1=" + idMap[fieldId] + ", field2=" + fieldName +
                                                    ", fieldId=" + fieldId + ']');
                }

                idMap[fieldId] = fieldName;
            }

            fields.Sort(Compare);

            Descriptor desc = new Descriptor(fields);

            _types[type] = desc;
        }
        /// <summary>
        /// Register type.
        /// </summary>
        /// <param name="type">Type.</param>
        /// <param name="typeId">Type ID.</param>
        /// <param name="converter">Name converter.</param>
        /// <param name="idMapper">ID mapper.</param>
        /// <param name="forceTimestamp">Force timestamp serialization for DateTime fields..</param>
        /// <returns>Resulting serializer.</returns>
        internal BinaryReflectiveSerializerInternal Register(Type type, int typeId, IBinaryNameMapper converter,
                                                             IBinaryIdMapper idMapper, bool forceTimestamp)
        {
            Debug.Assert(_wActions == null && _rActions == null);

            var fields = ReflectionUtils.GetAllFields(type).Where(x => !x.IsNotSerialized).ToList();

            IDictionary <int, string> idMap = new Dictionary <int, string>();

            foreach (FieldInfo field in fields)
            {
                string fieldName = BinaryUtils.CleanFieldName(field.Name);

                int fieldId = BinaryUtils.FieldId(typeId, fieldName, converter, idMapper);

                if (idMap.ContainsKey(fieldId))
                {
                    throw new BinaryObjectException("Conflicting field IDs [type=" +
                                                    type.Name + ", field1=" + idMap[fieldId] + ", field2=" + fieldName +
                                                    ", fieldId=" + fieldId + ']');
                }

                idMap[fieldId] = fieldName;
            }

            fields.Sort(Compare);

            var wActions = new BinaryReflectiveWriteAction[fields.Count];
            var rActions = new BinaryReflectiveReadAction[fields.Count];

            for (int i = 0; i < fields.Count; i++)
            {
                BinaryReflectiveWriteAction writeAction;
                BinaryReflectiveReadAction  readAction;

                BinaryReflectiveActions.GetTypeActions(fields[i], out writeAction, out readAction, _rawMode, forceTimestamp);

                wActions[i] = writeAction;
                rActions[i] = readAction;
            }

            var serDesc = SerializableTypeDescriptor.Get(type);

            return(new BinaryReflectiveSerializerInternal(wActions, rActions, _rawMode, serDesc));
        }
Пример #10
0
        /// <summary>
        /// Determines whether specified field should be written as timestamp.
        /// </summary>
        private static bool IsTimestamp(FieldInfo field, bool forceTimestamp, bool raw)
        {
            if (forceTimestamp)
            {
                return(true);
            }

            Debug.Assert(field != null && field.DeclaringType != null);

            var fieldName = BinaryUtils.CleanFieldName(field.Name);

            object[] attrs = null;

            if (fieldName != field.Name)
            {
                // Backing field, check corresponding property
                var prop = field.DeclaringType.GetProperty(fieldName, field.FieldType);

                if (prop != null)
                {
                    attrs = prop.GetCustomAttributes(true);
                }
            }

            attrs = attrs ?? field.GetCustomAttributes(true);

            if (attrs.Any(x => x is TimestampAttribute))
            {
                return(true);
            }

            // Special case for DateTime and query fields.
            // If a field is marked with [QuerySqlField], write it as TimeStamp so that queries work.
            // This is not needed in raw mode (queries do not work anyway).
            // It may cause issues when field has attribute, but is used in a cache without queries, and user
            // may expect non-UTC dates to work. However, such cases are rare, and there are workarounds.
            return(!raw && attrs.Any(x => x is QuerySqlFieldAttribute));
        }
Пример #11
0
        /// <summary>
        /// Determines whether specified field is a query field (has QueryFieldAttribute).
        /// </summary>
        private static bool IsQueryField(FieldInfo fieldInfo)
        {
            Debug.Assert(fieldInfo != null && fieldInfo.DeclaringType != null);

            var fieldName = BinaryUtils.CleanFieldName(fieldInfo.Name);

            object[] attrs = null;

            if (fieldName != fieldInfo.Name)
            {
                // Backing field, check corresponding property
                var prop = fieldInfo.DeclaringType.GetProperty(fieldName, fieldInfo.FieldType);

                if (prop != null)
                {
                    attrs = prop.GetCustomAttributes(true);
                }
            }

            attrs = attrs ?? fieldInfo.GetCustomAttributes(true);

            return(attrs.OfType <QuerySqlFieldAttribute>().Any());
        }
Пример #12
0
        /// <summary>
        /// Handle other type.
        /// </summary>
        /// <param name="field">The field.</param>
        /// <param name="writeAction">Write action.</param>
        /// <param name="readAction">Read action.</param>
        /// <param name="raw">Raw mode.</param>
        /// <param name="forceTimestamp">Force timestamp serialization for DateTime fields..</param>
        private static void HandleOther(FieldInfo field, out BinaryReflectiveWriteAction writeAction,
                                        out BinaryReflectiveReadAction readAction, bool raw, bool forceTimestamp)
        {
            var type = field.FieldType;

            var nullableType = Nullable.GetUnderlyingType(type);

            if (type == typeof(decimal))
            {
                writeAction = raw
                    ? GetRawWriter <decimal>(field, (w, o) => w.WriteDecimal(o))
                    : GetWriter <decimal>(field, (f, w, o) => w.WriteDecimal(f, o));
                readAction = raw
                    ? GetRawReader(field, r => r.ReadDecimal())
                    : GetReader(field, (f, r) => r.ReadDecimal(f));
            }
            else if (type == typeof(string))
            {
                writeAction = raw
                    ? GetRawWriter <string>(field, (w, o) => w.WriteString(o))
                    : GetWriter <string>(field, (f, w, o) => w.WriteString(f, o));
                readAction = raw
                    ? GetRawReader(field, r => r.ReadString())
                    : GetReader(field, (f, r) => r.ReadString(f));
            }
            else if (type == typeof(Guid))
            {
                writeAction = raw
                    ? GetRawWriter <Guid>(field, (w, o) => w.WriteGuid(o))
                    : GetWriter <Guid>(field, (f, w, o) => w.WriteGuid(f, o));
                readAction = raw
                    ? GetRawReader(field, r => r.ReadObject <Guid>())
                    : GetReader(field, (f, r) => r.ReadObject <Guid>(f));
            }
            else if (nullableType == typeof(Guid))
            {
                writeAction = raw
                    ? GetRawWriter <Guid?>(field, (w, o) => w.WriteGuid(o))
                    : GetWriter <Guid?>(field, (f, w, o) => w.WriteGuid(f, o));
                readAction = raw ? GetRawReader(field, r => r.ReadGuid()) : GetReader(field, (f, r) => r.ReadGuid(f));
            }
            else if ((nullableType ?? type).IsEnum &&
                     !new[] { typeof(long), typeof(ulong) }.Contains(Enum.GetUnderlyingType(nullableType ?? type)))
            {
                writeAction = raw
                    ? GetRawWriter <object>(field, (w, o) => w.WriteEnum(o))
                    : GetWriter <object>(field, (f, w, o) => w.WriteEnum(f, o));
                readAction = raw ? GetRawReader(field, MthdReadEnumRaw) : GetReader(field, MthdReadEnum);
            }
            else if (type == typeof(IDictionary) || type == typeof(Hashtable))
            {
                writeAction = raw
                    ? GetRawWriter <IDictionary>(field, (w, o) => w.WriteDictionary(o))
                    : GetWriter <IDictionary>(field, (f, w, o) => w.WriteDictionary(f, o));
                readAction = raw
                    ? GetRawReader(field, r => r.ReadDictionary())
                    : GetReader(field, (f, r) => r.ReadDictionary(f));
            }
            else if (type == typeof(ICollection) || type == typeof(ArrayList))
            {
                writeAction = raw
                    ? GetRawWriter <ICollection>(field, (w, o) => w.WriteCollection(o))
                    : GetWriter <ICollection>(field, (f, w, o) => w.WriteCollection(f, o));
                readAction = raw
                    ? GetRawReader(field, r => r.ReadCollection())
                    : GetReader(field, (f, r) => r.ReadCollection(f));
            }
            else if (type == typeof(DateTime) && IsTimestamp(field, forceTimestamp, raw))
            {
                writeAction = GetWriter <DateTime>(field, (f, w, o) => w.WriteTimestamp(f, o));
                readAction  = GetReader(field, (f, r) => r.ReadObject <DateTime>(f));
            }
            else if (nullableType == typeof(DateTime) && IsTimestamp(field, forceTimestamp, raw))
            {
                writeAction = GetWriter <DateTime?>(field, (f, w, o) => w.WriteTimestamp(f, o));
                readAction  = GetReader(field, (f, r) => r.ReadTimestamp(f));
            }
            else if (type.IsPointer)
            {
                unsafe
                {
                    // Expression trees do not work with pointers properly, use reflection.
                    var fieldName = BinaryUtils.CleanFieldName(field.Name);
                    writeAction = raw
                        ? (BinaryReflectiveWriteAction)((o, w) =>
                                                        w.GetRawWriter().WriteLong((long)Pointer.Unbox(field.GetValue(o))))
                        : ((o, w) => w.WriteLong(fieldName, (long)Pointer.Unbox(field.GetValue(o))));

                    readAction = raw
                        ? (BinaryReflectiveReadAction)((o, r) =>
                                                       field.SetValue(o, Pointer.Box((void *)r.GetRawReader().ReadLong(), field.FieldType)))
                        : ((o, r) => field.SetValue(o, Pointer.Box((void *)r.ReadLong(fieldName), field.FieldType)));
                }
            }
            else
            {
                writeAction = raw ? GetRawWriter(field, MthdWriteObjRaw) : GetWriter(field, MthdWriteObj);
                readAction  = raw ? GetRawReader(field, MthdReadObjRaw) : GetReader(field, MthdReadObj);
            }
        }