Пример #1
0
        private Action <object> CreateReader(PropertyInfo column, Dictionary <Type, Func <BinaryReader, object> > customReaders)
        {
            if (customReaders.ContainsKey(column.PropertyType))
            {
                var reader = customReaders[column.PropertyType];
                return(o => column.SetValue(o, reader(_columnReader)));
            }

            var paramObject = Expression.Parameter(typeof(object), "o");
            var typedObject = Expression.Convert(paramObject, column.DeclaringType);

            if (column.PropertyType == typeof(bool))
            {
                return(o => column.SetValue(o, _columnReader.ReadBoolean()));
            }
            if (column.PropertyType == typeof(bool?))
            {
                return(o => column.SetValue(o, _columnReader.ReadBoolean() ? _columnReader.ReadBoolean() : (bool?)null));
            }
            if (column.PropertyType == typeof(byte))
            {
                return(o => column.SetValue(o, _columnReader.ReadByte()));
            }
            if (column.PropertyType == typeof(byte?))
            {
                return(o => column.SetValue(o, _columnReader.ReadBoolean() ? _columnReader.ReadByte() : (byte?)null));
            }
            if (column.PropertyType == typeof(sbyte))
            {
                return(o => column.SetValue(o, _columnReader.ReadSByte()));
            }
            if (column.PropertyType == typeof(sbyte?))
            {
                return(o => column.SetValue(o, _columnReader.ReadBoolean() ? _columnReader.ReadSByte() : (sbyte?)null));
            }
            if (column.PropertyType == typeof(short))
            {
                return(o => column.SetValue(o, _columnReader.ReadInt16()));
            }
            if (column.PropertyType == typeof(short?))
            {
                return(o => column.SetValue(o, _columnReader.ReadBoolean() ? _columnReader.ReadInt16() : (short?)null));
            }
            if (column.PropertyType == typeof(ushort))
            {
                return(o => column.SetValue(o, _columnReader.ReadUInt16()));
            }
            if (column.PropertyType == typeof(ushort?))
            {
                return(o => column.SetValue(o, _columnReader.ReadBoolean() ? _columnReader.ReadUInt16() : (ushort?)null));
            }
            if (column.PropertyType == typeof(int))
            {
                return(o => column.SetValue(o, _columnReader.ReadInt32()));
            }
            if (column.PropertyType == typeof(int?))
            {
                return(o => column.SetValue(o, _columnReader.ReadBoolean() ? _columnReader.ReadInt32() : (int?)null));
            }
            if (column.PropertyType == typeof(uint))
            {
                return(o => column.SetValue(o, _columnReader.ReadUInt32()));
            }
            if (column.PropertyType == typeof(uint?))
            {
                return(o => column.SetValue(o, _columnReader.ReadBoolean() ? _columnReader.ReadUInt32() : (uint?)null));
            }
            if (column.PropertyType == typeof(long))
            {
                return(o => column.SetValue(o, _columnReader.ReadInt64()));
            }
            if (column.PropertyType == typeof(long?))
            {
                return(o => column.SetValue(o, _columnReader.ReadBoolean() ? _columnReader.ReadInt64() : (long?)null));
            }
            if (column.PropertyType == typeof(ulong))
            {
                return(o => column.SetValue(o, _columnReader.ReadUInt64()));
            }
            if (column.PropertyType == typeof(ulong?))
            {
                return(o => column.SetValue(o, _columnReader.ReadBoolean() ? _columnReader.ReadUInt64() : (ulong?)null));
            }
            if (column.PropertyType == typeof(Guid))
            {
                return(o => column.SetValue(o, new Guid(_columnReader.ReadBytes(16))));
            }
            if (column.PropertyType == typeof(Guid?))
            {
                return(o => column.SetValue(o, _columnReader.ReadBoolean() ? new Guid(_columnReader.ReadBytes(16)) : (Guid?)null));
            }
            if (column.PropertyType == typeof(decimal))
            {
                var reader     = new DecimalReader(_columnStream);
                var paramValue = Expression.Parameter(typeof(decimal), "d");
                var call       = Expression.Call(typedObject, column.GetSetMethod(), paramValue);

                var setter = Expression.Lambda <Action <object, decimal> >(call, paramObject, paramValue).Compile();

                return(o => setter(o, reader.ReadDecimal()));
            }
            if (column.PropertyType == typeof(decimal?))
            {
                return(o => column.SetValue(o, _columnReader.ReadBoolean() ? _columnReader.ReadDecimal() : (decimal?)null));
            }
            if (column.PropertyType == typeof(DateTime))
            {
                return(o => column.SetValue(o, new DateTime(_columnReader.ReadInt64())));
            }
            if (column.PropertyType == typeof(DateTime?))
            {
                return(o => column.SetValue(o, _columnReader.ReadBoolean() ? new DateTime(_columnReader.ReadInt64()) : (DateTime?)null));
            }
            if (column.PropertyType == typeof(DateTimeOffset))
            {
                return(o => column.SetValue(o, new DateTimeOffset(_columnReader.ReadInt64(), new TimeSpan(_columnReader.ReadInt64()))));
            }
            if (column.PropertyType == typeof(DateTimeOffset?))
            {
                return(o => column.SetValue(o, _columnReader.ReadBoolean() ? new DateTimeOffset(_columnReader.ReadInt64(), new TimeSpan(_columnReader.ReadInt64())) : (DateTimeOffset?)null));
            }
            if (column.PropertyType == typeof(string))
            {
                return(o => column.SetValue(o, _columnReader.ReadString()));
            }
            if (column.PropertyType.IsEnum)
            {
                var underlyingType = Enum.GetUnderlyingType(column.PropertyType);

                if (underlyingType == typeof(byte))
                {
                    return(o => column.SetValue(o, _columnReader.ReadByte()));
                }

                if (underlyingType == typeof(short))
                {
                    return(o => column.SetValue(o, _columnReader.ReadInt16()));
                }

                if (underlyingType == typeof(int))
                {
                    return(o => column.SetValue(o, _columnReader.ReadInt32()));
                }

                throw new NotSupportedException("Unsupported underlying enum type: " + underlyingType.FullName);
            }
            if (Nullable.GetUnderlyingType(column.PropertyType)?.IsEnum == true)
            {
                var underlyingType = Enum.GetUnderlyingType(Nullable.GetUnderlyingType(column.PropertyType));

                if (underlyingType == typeof(byte))
                {
                    return(o => column.SetValue(o, _columnReader.ReadBoolean() ? (object)_columnReader.ReadByte() : null));
                }

                if (underlyingType == typeof(short))
                {
                    return(o => column.SetValue(o, _columnReader.ReadBoolean() ? (object)_columnReader.ReadInt16() : null));
                }

                if (underlyingType == typeof(int))
                {
                    return(o => column.SetValue(o, _columnReader.ReadBoolean() ? (object)_columnReader.ReadInt32() : null));
                }

                throw new NotSupportedException("Unsupported underlying enum type: " + underlyingType.FullName);
            }
            if (column.PropertyType.IsArray)
            {
                var reader = new TypeReader(_path + column.Name + ".", column.PropertyType.GetElementType(), customReaders);
                return(o =>
                {
                    var isNonNull = _columnReader.ReadBoolean();

                    if (!isNonNull)
                    {
                        column.SetValue(o, null);
                    }
                    else
                    {
                        var length = _columnReader.ReadUInt16();
                        var array = (Array)Activator.CreateInstance(column.PropertyType, length);

                        for (int i = 0; i < length; i++)
                        {
                            array.SetValue(reader.ReadNew(), i);
                        }

                        column.SetValue(o, array);
                    }
                });
            }
            if (!column.PropertyType.IsValueType)
            {
                var reader = new TypeReader(_path + column.Name + ".", column.PropertyType, customReaders);
                return(o =>
                {
                    var isNonNull = _columnReader.ReadBoolean();
                    column.SetValue(o, isNonNull ? reader.ReadNew() : null);
                });
            }

            throw new Exception("Unsupported column type " + column.PropertyType.Name);
        }
Пример #2
0
        internal void Dispatch(Dictionary <Type, Type> knownProxies, Dictionary <Type, Action <object> > handlers)
        {
            // TODO: Maybe we should create a new reader each time?
            _recordsStream.Seek(0, SeekOrigin.Begin);

            var readerStream = new UInt16Reader(_recordsStream);

            // TODO: Maybe we should share column readers?
            var typesMap    = new Type[ushort.MaxValue];
            var typeReaders = new TypeReader[ushort.MaxValue];

            foreach (var type in handlers.Keys)
            {
                var originalType = type;

                if (knownProxies.ContainsKey(type))
                {
                    originalType = knownProxies[type];
                }

                if (_typeIdsMap.ContainsKey(originalType.FullName))
                {
                    var typeId = _typeIdsMap[originalType.FullName];
                    var path   = _folder + "\\" + originalType.FullName + "\\";

                    typesMap[typeId]    = type;
                    typeReaders[typeId] = new TypeReader(path, type, _customReaders)
                    {
                        Handler = handlers[type]
                    };
                }
            }

            // Keep reading while there's more data
            ushort[] records = null;
            while ((records = readerStream.ReadUInt16s()).Length != 0)
            {
                // Read as many values as we can from the reader's buffer
                for (var i = 0; i < records.Length; i++)
                {
                    var typeId     = records[i];
                    var typeReader = typeReaders[typeId];

                    if (typeReader == null)
                    {
                        continue;
                    }

                    var handler  = typeReader.Handler;
                    var instance = typeReader.Read();

                    handler(instance);
                }
            }

            foreach (var type in typeReaders)
            {
                if (type == null)
                {
                    continue;
                }

                type.Dispose();
            }
        }