ignite-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From voze...@apache.org
Subject [17/24] ignite git commit: IGNITE-1845: Adopted new binary API in .Net.
Date Wed, 11 Nov 2015 09:13:04 GMT
http://git-wip-us.apache.org/repos/asf/ignite/blob/894057e5/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryReader.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryReader.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryReader.cs
new file mode 100644
index 0000000..1dec7ba
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryReader.cs
@@ -0,0 +1,940 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+namespace Apache.Ignite.Core.Impl.Binary
+{
+    using System;
+    using System.Collections;
+    using System.Collections.Generic;
+    using System.Diagnostics.CodeAnalysis;
+    using System.IO;
+    using System.Runtime.Serialization;
+    using Apache.Ignite.Core.Binary;
+    using Apache.Ignite.Core.Impl.Binary.IO;
+    using Apache.Ignite.Core.Impl.Binary.Structure;
+    using Apache.Ignite.Core.Impl.Common;
+
+    /// <summary>
+    /// Binary reader implementation. 
+    /// </summary>
+    internal class BinaryReader : IBinaryReader, IBinaryRawReader
+    {
+        /** Marshaller. */
+        private readonly Marshaller _marsh;
+
+        /** Type descriptors. */
+        private readonly IDictionary<long, IBinaryTypeDescriptor> _descs;
+
+        /** Parent builder. */
+        private readonly BinaryObjectBuilder _builder;
+
+        /** Handles. */
+        private BinaryReaderHandleDictionary _hnds;
+
+        /** Current position. */
+        private int _curPos;
+
+        /** Current raw flag. */
+        private bool _curRaw;
+
+        /** Detach flag. */
+        private bool _detach;
+
+        /** Binary read mode. */
+        private BinaryMode _mode;
+
+        /** Current type structure tracker. */
+        private BinaryStructureTracker _curStruct;
+
+        /** Current schema. */
+        private int[] _curSchema;
+
+        /** Current schema with positions. */
+        private Dictionary<int, int> _curSchemaMap;
+
+        /** Current header. */
+        private BinaryObjectHeader _curHdr;
+
+        /// <summary>
+        /// Constructor.
+        /// </summary>
+        /// <param name="marsh">Marshaller.</param>
+        /// <param name="descs">Descriptors.</param>
+        /// <param name="stream">Input stream.</param>
+        /// <param name="mode">The mode.</param>
+        /// <param name="builder">Builder.</param>
+        public BinaryReader
+            (Marshaller marsh,
+            IDictionary<long, IBinaryTypeDescriptor> descs, 
+            IBinaryStream stream, 
+            BinaryMode mode,
+            BinaryObjectBuilder builder)
+        {
+            _marsh = marsh;
+            _descs = descs;
+            _mode = mode;
+            _builder = builder;
+
+            Stream = stream;
+        }
+
+        /// <summary>
+        /// Gets the marshaller.
+        /// </summary>
+        public Marshaller Marshaller
+        {
+            get { return _marsh; }
+        }
+
+        /** <inheritdoc /> */
+        public IBinaryRawReader GetRawReader()
+        {
+            MarkRaw();
+
+            return this;
+        }
+
+        /** <inheritdoc /> */
+        public bool ReadBoolean(string fieldName)
+        {
+            return ReadField(fieldName, r => r.ReadBoolean(), BinaryUtils.TypeBool);
+        }
+
+        /** <inheritdoc /> */
+        public bool ReadBoolean()
+        {
+            return Stream.ReadBool();
+        }
+
+        /** <inheritdoc /> */
+        public bool[] ReadBooleanArray(string fieldName)
+        {
+            return ReadField(fieldName, BinaryUtils.ReadBooleanArray, BinaryUtils.TypeArrayBool);
+        }
+
+        /** <inheritdoc /> */
+        public bool[] ReadBooleanArray()
+        {
+            return Read(BinaryUtils.ReadBooleanArray, BinaryUtils.TypeArrayBool);
+        }
+
+        /** <inheritdoc /> */
+        public byte ReadByte(string fieldName)
+        {
+            return ReadField(fieldName, ReadByte, BinaryUtils.TypeByte);
+        }
+
+        /** <inheritdoc /> */
+        public byte ReadByte()
+        {
+            return Stream.ReadByte();
+        }
+
+        /** <inheritdoc /> */
+        public byte[] ReadByteArray(string fieldName)
+        {
+            return ReadField(fieldName, BinaryUtils.ReadByteArray, BinaryUtils.TypeArrayByte);
+        }
+
+        /** <inheritdoc /> */
+        public byte[] ReadByteArray()
+        {
+            return Read(BinaryUtils.ReadByteArray, BinaryUtils.TypeArrayByte);
+        }
+
+        /** <inheritdoc /> */
+        public short ReadShort(string fieldName)
+        {
+            return ReadField(fieldName, ReadShort, BinaryUtils.TypeShort);
+        }
+
+        /** <inheritdoc /> */
+        public short ReadShort()
+        {
+            return Stream.ReadShort();
+        }
+
+        /** <inheritdoc /> */
+        public short[] ReadShortArray(string fieldName)
+        {
+            return ReadField(fieldName, BinaryUtils.ReadShortArray, BinaryUtils.TypeArrayShort);
+        }
+
+        /** <inheritdoc /> */
+        public short[] ReadShortArray()
+        {
+            return Read(BinaryUtils.ReadShortArray, BinaryUtils.TypeArrayShort);
+        }
+
+        /** <inheritdoc /> */
+        public char ReadChar(string fieldName)
+        {
+            return ReadField(fieldName, ReadChar, BinaryUtils.TypeChar);
+        }
+
+        /** <inheritdoc /> */
+        public char ReadChar()
+        {
+            return Stream.ReadChar();
+        }
+
+        /** <inheritdoc /> */
+        public char[] ReadCharArray(string fieldName)
+        {
+            return ReadField(fieldName, BinaryUtils.ReadCharArray, BinaryUtils.TypeArrayChar);
+        }
+
+        /** <inheritdoc /> */
+        public char[] ReadCharArray()
+        {
+            return Read(BinaryUtils.ReadCharArray, BinaryUtils.TypeArrayChar);
+        }
+
+        /** <inheritdoc /> */
+        public int ReadInt(string fieldName)
+        {
+            return ReadField(fieldName, ReadInt, BinaryUtils.TypeInt);
+        }
+
+        /** <inheritdoc /> */
+        public int ReadInt()
+        {
+            return Stream.ReadInt();
+        }
+
+        /** <inheritdoc /> */
+        public int[] ReadIntArray(string fieldName)
+        {
+            return ReadField(fieldName, BinaryUtils.ReadIntArray, BinaryUtils.TypeArrayInt);
+        }
+
+        /** <inheritdoc /> */
+        public int[] ReadIntArray()
+        {
+            return Read(BinaryUtils.ReadIntArray, BinaryUtils.TypeArrayInt);
+        }
+
+        /** <inheritdoc /> */
+        public long ReadLong(string fieldName)
+        {
+            return ReadField(fieldName, ReadLong, BinaryUtils.TypeLong);
+        }
+
+        /** <inheritdoc /> */
+        public long ReadLong()
+        {
+            return Stream.ReadLong();
+        }
+
+        /** <inheritdoc /> */
+        public long[] ReadLongArray(string fieldName)
+        {
+            return ReadField(fieldName, BinaryUtils.ReadLongArray, BinaryUtils.TypeArrayLong);
+        }
+
+        /** <inheritdoc /> */
+        public long[] ReadLongArray()
+        {
+            return Read(BinaryUtils.ReadLongArray, BinaryUtils.TypeArrayLong);
+        }
+
+        /** <inheritdoc /> */
+        public float ReadFloat(string fieldName)
+        {
+            return ReadField(fieldName, ReadFloat, BinaryUtils.TypeFloat);
+        }
+
+        /** <inheritdoc /> */
+        public float ReadFloat()
+        {
+            return Stream.ReadFloat();
+        }
+
+        /** <inheritdoc /> */
+        public float[] ReadFloatArray(string fieldName)
+        {
+            return ReadField(fieldName, BinaryUtils.ReadFloatArray, BinaryUtils.TypeArrayFloat);
+        }
+
+        /** <inheritdoc /> */
+        public float[] ReadFloatArray()
+        {
+            return Read(BinaryUtils.ReadFloatArray, BinaryUtils.TypeArrayFloat);
+        }
+
+        /** <inheritdoc /> */
+        public double ReadDouble(string fieldName)
+        {
+            return ReadField(fieldName, ReadDouble, BinaryUtils.TypeDouble);
+        }
+
+        /** <inheritdoc /> */
+        public double ReadDouble()
+        {
+            return Stream.ReadDouble();
+        }
+
+        /** <inheritdoc /> */
+        public double[] ReadDoubleArray(string fieldName)
+        {
+            return ReadField(fieldName, BinaryUtils.ReadDoubleArray, BinaryUtils.TypeArrayDouble);
+        }
+
+        /** <inheritdoc /> */
+        public double[] ReadDoubleArray()
+        {
+            return Read(BinaryUtils.ReadDoubleArray, BinaryUtils.TypeArrayDouble);
+        }
+
+        /** <inheritdoc /> */
+        public decimal? ReadDecimal(string fieldName)
+        {
+            return ReadField(fieldName, BinaryUtils.ReadDecimal, BinaryUtils.TypeDecimal);
+        }
+
+        /** <inheritdoc /> */
+        public decimal? ReadDecimal()
+        {
+            return Read(BinaryUtils.ReadDecimal, BinaryUtils.TypeDecimal);
+        }
+
+        /** <inheritdoc /> */
+        public decimal?[] ReadDecimalArray(string fieldName)
+        {
+            return ReadField(fieldName, BinaryUtils.ReadDecimalArray, BinaryUtils.TypeArrayDecimal);
+        }
+
+        /** <inheritdoc /> */
+        public decimal?[] ReadDecimalArray()
+        {
+            return Read(BinaryUtils.ReadDecimalArray, BinaryUtils.TypeArrayDecimal);
+        }
+
+        /** <inheritdoc /> */
+        public DateTime? ReadTimestamp(string fieldName)
+        {
+            return ReadField(fieldName, BinaryUtils.ReadTimestamp, BinaryUtils.TypeTimestamp);
+        }
+
+        /** <inheritdoc /> */
+        public DateTime? ReadTimestamp()
+        {
+            return Read(BinaryUtils.ReadTimestamp, BinaryUtils.TypeTimestamp);
+        }
+        
+        /** <inheritdoc /> */
+        public DateTime?[] ReadTimestampArray(string fieldName)
+        {
+            return ReadField(fieldName, BinaryUtils.ReadTimestampArray, BinaryUtils.TypeArrayTimestamp);
+        }
+        
+        /** <inheritdoc /> */
+        public DateTime?[] ReadTimestampArray()
+        {
+            return Read(BinaryUtils.ReadTimestampArray, BinaryUtils.TypeArrayTimestamp);
+        }
+        
+        /** <inheritdoc /> */
+        public string ReadString(string fieldName)
+        {
+            return ReadField(fieldName, BinaryUtils.ReadString, BinaryUtils.TypeString);
+        }
+
+        /** <inheritdoc /> */
+        public string ReadString()
+        {
+            return Read(BinaryUtils.ReadString, BinaryUtils.TypeString);
+        }
+
+        /** <inheritdoc /> */
+        public string[] ReadStringArray(string fieldName)
+        {
+            return ReadField(fieldName, r => BinaryUtils.ReadArray<string>(r, false), BinaryUtils.TypeArrayString);
+        }
+
+        /** <inheritdoc /> */
+        public string[] ReadStringArray()
+        {
+            return Read(r => BinaryUtils.ReadArray<string>(r, false), BinaryUtils.TypeArrayString);
+        }
+
+        /** <inheritdoc /> */
+        public Guid? ReadGuid(string fieldName)
+        {
+            return ReadField(fieldName, BinaryUtils.ReadGuid, BinaryUtils.TypeGuid);
+        }
+
+        /** <inheritdoc /> */
+        public Guid? ReadGuid()
+        {
+            return Read(BinaryUtils.ReadGuid, BinaryUtils.TypeGuid);
+        }
+
+        /** <inheritdoc /> */
+        public Guid?[] ReadGuidArray(string fieldName)
+        {
+            return ReadField(fieldName, r => BinaryUtils.ReadArray<Guid?>(r, false), BinaryUtils.TypeArrayGuid);
+        }
+
+        /** <inheritdoc /> */
+        public Guid?[] ReadGuidArray()
+        {
+            return Read(r => BinaryUtils.ReadArray<Guid?>(r, false), BinaryUtils.TypeArrayGuid);
+        }
+
+        /** <inheritdoc /> */
+        public T ReadEnum<T>(string fieldName)
+        {
+            return ReadField(fieldName, BinaryUtils.ReadEnum<T>, BinaryUtils.TypeEnum);
+        }
+
+        /** <inheritdoc /> */
+        public T ReadEnum<T>()
+        {
+            return Read(BinaryUtils.ReadEnum<T>, BinaryUtils.TypeEnum);
+        }
+
+        /** <inheritdoc /> */
+        public T[] ReadEnumArray<T>(string fieldName)
+        {
+            return ReadField(fieldName, r => BinaryUtils.ReadArray<T>(r, true), BinaryUtils.TypeArrayEnum);
+        }
+
+        /** <inheritdoc /> */
+        public T[] ReadEnumArray<T>()
+        {
+            return Read(r => BinaryUtils.ReadArray<T>(r, true), BinaryUtils.TypeArrayEnum);
+        }
+
+        /** <inheritdoc /> */
+        public T ReadObject<T>(string fieldName)
+        {
+            if (_curRaw)
+                throw new BinaryObjectException("Cannot read named fields after raw data is read.");
+
+            if (SeekField(fieldName))
+                return Deserialize<T>();
+
+            return default(T);
+        }
+
+        /** <inheritdoc /> */
+        public T ReadObject<T>()
+        {
+            return Deserialize<T>();
+        }
+
+        /** <inheritdoc /> */
+        public T[] ReadArray<T>(string fieldName)
+        {
+            return ReadField(fieldName, r => BinaryUtils.ReadArray<T>(r, true), BinaryUtils.TypeArray);
+        }
+
+        /** <inheritdoc /> */
+        public T[] ReadArray<T>()
+        {
+            return Read(r => BinaryUtils.ReadArray<T>(r, true), BinaryUtils.TypeArray);
+        }
+
+        /** <inheritdoc /> */
+        public ICollection ReadCollection(string fieldName)
+        {
+            return ReadCollection(fieldName, null, null);
+        }
+
+        /** <inheritdoc /> */
+        public ICollection ReadCollection()
+        {
+            return ReadCollection(null, null);
+        }
+
+        /** <inheritdoc /> */
+        public ICollection ReadCollection(string fieldName, CollectionFactory factory,
+            CollectionAdder adder)
+        {
+            return ReadField(fieldName, r => BinaryUtils.ReadCollection(r, factory, adder), BinaryUtils.TypeCollection);
+        }
+
+        /** <inheritdoc /> */
+        public ICollection ReadCollection(CollectionFactory factory,
+            CollectionAdder adder)
+        {
+            return Read(r => BinaryUtils.ReadCollection(r, factory, adder), BinaryUtils.TypeCollection);
+        }
+
+        /** <inheritdoc /> */
+        public IDictionary ReadDictionary(string fieldName)
+        {
+            return ReadDictionary(fieldName, null);
+        }
+
+        /** <inheritdoc /> */
+        public IDictionary ReadDictionary()
+        {
+            return ReadDictionary((DictionaryFactory)null);
+        }
+
+        /** <inheritdoc /> */
+        public IDictionary ReadDictionary(string fieldName, DictionaryFactory factory)
+        {
+            return ReadField(fieldName, r => BinaryUtils.ReadDictionary(r, factory), BinaryUtils.TypeDictionary);
+        }
+
+        /** <inheritdoc /> */
+        public IDictionary ReadDictionary(DictionaryFactory factory)
+        {
+            return Read(r => BinaryUtils.ReadDictionary(r, factory), BinaryUtils.TypeDictionary);
+        }
+
+        /// <summary>
+        /// Enable detach mode for the next object read. 
+        /// </summary>
+        public void DetachNext()
+        {
+            _detach = true;
+        }
+
+        /// <summary>
+        /// Deserialize object.
+        /// </summary>
+        /// <returns>Deserialized object.</returns>
+        public T Deserialize<T>()
+        {
+            int pos = Stream.Position;
+
+            byte hdr = Stream.ReadByte();
+
+            var doDetach = _detach;  // save detach flag into a var and reset so it does not go deeper
+
+            _detach = false;
+
+            switch (hdr)
+            {
+                case BinaryUtils.HdrNull:
+                    if (default(T) != null)
+                        throw new BinaryObjectException(string.Format("Invalid data on deserialization. " +
+                            "Expected: '{0}' But was: null", typeof (T)));
+
+                    return default(T);
+
+                case BinaryUtils.HdrHnd:
+                    return ReadHandleObject<T>(pos);
+
+                case BinaryUtils.HdrFull:
+                    return ReadFullObject<T>(pos);
+
+                case BinaryUtils.TypeBinary:
+                    return ReadBinaryObject<T>(doDetach);
+            }
+
+            if (BinaryUtils.IsPredefinedType(hdr))
+                return BinarySystemHandlers.ReadSystemType<T>(hdr, this);
+
+            throw new BinaryObjectException("Invalid header on deserialization [pos=" + pos + ", hdr=" + hdr + ']');
+        }
+
+        /// <summary>
+        /// Reads the binary object.
+        /// </summary>
+        private T ReadBinaryObject<T>(bool doDetach)
+        {
+            var len = Stream.ReadInt();
+
+            var binaryBytesPos = Stream.Position;
+
+            if (_mode != BinaryMode.Deserialize)
+                return TypeCaster<T>.Cast(ReadAsBinary(binaryBytesPos, len, doDetach));
+
+            Stream.Seek(len, SeekOrigin.Current);
+
+            var offset = Stream.ReadInt();
+
+            var retPos = Stream.Position;
+
+            Stream.Seek(binaryBytesPos + offset, SeekOrigin.Begin);
+
+            _mode = BinaryMode.KeepBinary;
+
+            try
+            {
+                return Deserialize<T>();
+            }
+            finally
+            {
+                _mode = BinaryMode.Deserialize;
+
+                Stream.Seek(retPos, SeekOrigin.Begin);
+            }
+        }
+
+        /// <summary>
+        /// Reads the binary object in binary form.
+        /// </summary>
+        private BinaryObject ReadAsBinary(int binaryBytesPos, int dataLen, bool doDetach)
+        {
+            try
+            {
+                Stream.Seek(dataLen + binaryBytesPos, SeekOrigin.Begin);
+
+                var offs = Stream.ReadInt(); // offset inside data
+
+                var pos = binaryBytesPos + offs;
+
+                var hdr = BinaryObjectHeader.Read(Stream, pos);
+
+                if (!doDetach)
+                    return new BinaryObject(_marsh, Stream.GetArray(), pos, hdr);
+
+                Stream.Seek(pos, SeekOrigin.Begin);
+
+                return new BinaryObject(_marsh, Stream.ReadByteArray(hdr.Length), 0, hdr);
+            }
+            finally
+            {
+                Stream.Seek(binaryBytesPos + dataLen + 4, SeekOrigin.Begin);
+            }
+        }
+
+        /// <summary>
+        /// Reads the full object.
+        /// </summary>
+        [SuppressMessage("Microsoft.Performance", "CA1804:RemoveUnusedLocals", MessageId = "hashCode")]
+        private T ReadFullObject<T>(int pos)
+        {
+            var hdr = BinaryObjectHeader.Read(Stream, pos);
+
+            // Validate protocol version.
+            BinaryUtils.ValidateProtocolVersion(hdr.Version);
+
+            try
+            {
+                // Already read this object?
+                object hndObj;
+
+                if (_hnds != null && _hnds.TryGetValue(pos, out hndObj))
+                    return (T) hndObj;
+
+                if (hdr.IsUserType && _mode == BinaryMode.ForceBinary)
+                {
+                    BinaryObject portObj;
+
+                    if (_detach)
+                    {
+                        Stream.Seek(pos, SeekOrigin.Begin);
+
+                        portObj = new BinaryObject(_marsh, Stream.ReadByteArray(hdr.Length), 0, hdr);
+                    }
+                    else
+                        portObj = new BinaryObject(_marsh, Stream.GetArray(), pos, hdr);
+
+                    T obj = _builder == null ? TypeCaster<T>.Cast(portObj) : TypeCaster<T>.Cast(_builder.Child(portObj));
+
+                    AddHandle(pos, obj);
+
+                    return obj;
+                }
+                else
+                {
+                    // Find descriptor.
+                    IBinaryTypeDescriptor desc;
+
+                    if (!_descs.TryGetValue(BinaryUtils.TypeKey(hdr.IsUserType, hdr.TypeId), out desc))
+                        throw new BinaryObjectException("Unknown type ID: " + hdr.TypeId);
+
+                    // Instantiate object. 
+                    if (desc.Type == null)
+                        throw new BinaryObjectException("No matching type found for object [typeId=" +
+                                                    desc.TypeId + ", typeName=" + desc.TypeName + ']');
+
+                    // Preserve old frame.
+                    var oldHdr = _curHdr;
+                    int oldPos = _curPos;
+                    var oldStruct = _curStruct;
+                    bool oldRaw = _curRaw;
+                    var oldSchema = _curSchema;
+                    var oldSchemaMap = _curSchemaMap;
+
+                    // Set new frame.
+                    _curHdr = hdr;
+                    _curPos = pos;
+                    
+                    _curSchema = desc.Schema.Get(hdr.SchemaId);
+
+                    if (_curSchema == null)
+                    {
+                        _curSchema = ReadSchema();
+
+                        desc.Schema.Add(hdr.SchemaId, _curSchema);
+                    }
+
+                    _curStruct = new BinaryStructureTracker(desc, desc.ReaderTypeStructure);
+                    _curRaw = false;
+
+                    // Read object.
+                    Stream.Seek(pos + BinaryObjectHeader.Size, SeekOrigin.Begin);
+
+                    object obj;
+
+                    var sysSerializer = desc.Serializer as IBinarySystemTypeSerializer;
+
+                    if (sysSerializer != null)
+                        obj = sysSerializer.ReadInstance(this);
+                    else
+                    {
+                        try
+                        {
+                            obj = FormatterServices.GetUninitializedObject(desc.Type);
+
+                            // Save handle.
+                            AddHandle(pos, obj);
+                        }
+                        catch (Exception e)
+                        {
+                            throw new BinaryObjectException("Failed to create type instance: " +
+                                                        desc.Type.AssemblyQualifiedName, e);
+                        }
+
+                        desc.Serializer.ReadBinary(obj, this);
+                    }
+
+                    _curStruct.UpdateReaderStructure();
+
+                    // Restore old frame.
+                    _curHdr = oldHdr;
+                    _curPos = oldPos;
+                    _curStruct = oldStruct;
+                    _curRaw = oldRaw;
+                    _curSchema = oldSchema;
+                    _curSchemaMap = oldSchemaMap;
+
+                    // Process wrappers. We could introduce a common interface, but for only 2 if-else is faster.
+                    var wrappedSerializable = obj as SerializableObjectHolder;
+
+                    if (wrappedSerializable != null) 
+                        return (T) wrappedSerializable.Item;
+
+                    var wrappedDateTime = obj as DateTimeHolder;
+
+                    if (wrappedDateTime != null)
+                        return TypeCaster<T>.Cast(wrappedDateTime.Item);
+                    
+                    return (T) obj;
+                }
+            }
+            finally
+            {
+                // Advance stream pointer.
+                Stream.Seek(pos + hdr.Length, SeekOrigin.Begin);
+            }
+        }
+
+        /// <summary>
+        /// Reads the schema.
+        /// </summary>
+        private int[] ReadSchema()
+        {
+            Stream.Seek(_curPos + _curHdr.SchemaOffset, SeekOrigin.Begin);
+
+            var count = _curHdr.SchemaFieldCount;
+
+            var offsetSize = _curHdr.SchemaFieldOffsetSize;
+
+            var res = new int[count];
+
+            for (int i = 0; i < count; i++)
+            {
+                res[i] = Stream.ReadInt();
+                Stream.Seek(offsetSize, SeekOrigin.Current);
+            }
+
+            return res;
+        }
+        /// <summary>
+        /// Reads the handle object.
+        /// </summary>
+        private T ReadHandleObject<T>(int pos)
+        {
+            // Get handle position.
+            int hndPos = pos - Stream.ReadInt();
+
+            int retPos = Stream.Position;
+
+            try
+            {
+                object hndObj;
+
+                if (_builder == null || !_builder.TryGetCachedField(hndPos, out hndObj))
+                {
+                    if (_hnds == null || !_hnds.TryGetValue(hndPos, out hndObj))
+                    {
+                        // No such handler, i.e. we trying to deserialize inner object before deserializing outer.
+                        Stream.Seek(hndPos, SeekOrigin.Begin);
+
+                        hndObj = Deserialize<T>();
+                    }
+
+                    // Notify builder that we deserialized object on other location.
+                    if (_builder != null)
+                        _builder.CacheField(hndPos, hndObj);
+                }
+
+                return (T) hndObj;
+            }
+            finally
+            {
+                // Position stream to correct place.
+                Stream.Seek(retPos, SeekOrigin.Begin);
+            }
+        }
+
+        /// <summary>
+        /// Adds a handle to the dictionary.
+        /// </summary>
+        /// <param name="pos">Position.</param>
+        /// <param name="obj">Object.</param>
+        private void AddHandle(int pos, object obj)
+        {
+            if (_hnds == null)
+                _hnds = new BinaryReaderHandleDictionary(pos, obj);
+            else
+                _hnds.Add(pos, obj);
+        }
+
+        /// <summary>
+        /// Underlying stream.
+        /// </summary>
+        public IBinaryStream Stream
+        {
+            get;
+            private set;
+        }
+
+        /// <summary>
+        /// Mark current output as raw. 
+        /// </summary>
+        private void MarkRaw()
+        {
+            if (!_curRaw)
+            {
+                _curRaw = true;
+
+                Stream.Seek(_curPos + _curHdr.GetRawOffset(Stream, _curPos), SeekOrigin.Begin);
+            }
+        }
+
+        /// <summary>
+        /// Determines whether header at current position is HDR_NULL.
+        /// </summary>
+        private bool IsNotNullHeader(byte expHdr)
+        {
+            var hdr = ReadByte();
+            
+            if (hdr == BinaryUtils.HdrNull)
+                return false;
+
+            if (expHdr != hdr)
+                throw new BinaryObjectException(string.Format("Invalid header on deserialization. " +
+                                                          "Expected: {0} but was: {1}", expHdr, hdr));
+
+            return true;
+        }
+
+        /// <summary>
+        /// Seeks the field by name, reads header and returns true if field is present and header is not null.
+        /// </summary>
+        private bool SeekField(string fieldName, byte expHdr)
+        {
+            if (!SeekField(fieldName)) 
+                return false;
+
+            // Expected read order, no need to seek.
+            return IsNotNullHeader(expHdr);
+        }
+
+        /// <summary>
+        /// Seeks the field by name.
+        /// </summary>
+        private bool SeekField(string fieldName)
+        {
+            if (_curRaw)
+                throw new BinaryObjectException("Cannot read named fields after raw data is read.");
+
+            if (_curHdr.IsRawOnly)
+                return false;
+
+            var actionId = _curStruct.CurStructAction;
+
+            var fieldId = _curStruct.GetFieldId(fieldName);
+
+            if (_curSchema == null || actionId >= _curSchema.Length || fieldId != _curSchema[actionId])
+            {
+                _curSchema = null; // read order is different, ignore schema for future reads
+
+                _curSchemaMap = _curSchemaMap ?? _curHdr.ReadSchemaAsDictionary(Stream, _curPos);
+
+                int pos;
+
+                if (!_curSchemaMap.TryGetValue(fieldId, out pos))
+                    return false;
+
+                Stream.Seek(pos, SeekOrigin.Begin);
+            }
+
+            return true;
+        }
+
+        /// <summary>
+        /// Seeks specified field and invokes provided func.
+        /// </summary>
+        private T ReadField<T>(string fieldName, Func<IBinaryStream, T> readFunc, byte expHdr)
+        {
+            return SeekField(fieldName, expHdr) ? readFunc(Stream) : default(T);
+        }
+
+        /// <summary>
+        /// Seeks specified field and invokes provided func.
+        /// </summary>
+        private T ReadField<T>(string fieldName, Func<BinaryReader, T> readFunc, byte expHdr)
+        {
+            return SeekField(fieldName, expHdr) ? readFunc(this) : default(T);
+        }
+
+        /// <summary>
+        /// Seeks specified field and invokes provided func.
+        /// </summary>
+        private T ReadField<T>(string fieldName, Func<T> readFunc, byte expHdr)
+        {
+            return SeekField(fieldName, expHdr) ? readFunc() : default(T);
+        }
+
+        /// <summary>
+        /// Reads header and invokes specified func if the header is not null.
+        /// </summary>
+        private T Read<T>(Func<BinaryReader, T> readFunc, byte expHdr)
+        {
+            return IsNotNullHeader(expHdr) ? readFunc(this) : default(T);
+        }
+
+        /// <summary>
+        /// Reads header and invokes specified func if the header is not null.
+        /// </summary>
+        private T Read<T>(Func<IBinaryStream, T> readFunc, byte expHdr)
+        {
+            return IsNotNullHeader(expHdr) ? readFunc(Stream) : default(T);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/894057e5/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryReaderExtensions.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryReaderExtensions.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryReaderExtensions.cs
new file mode 100644
index 0000000..c3dcc3a
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryReaderExtensions.cs
@@ -0,0 +1,52 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+namespace Apache.Ignite.Core.Impl.Binary
+{
+    using System.Collections.Generic;
+    using Apache.Ignite.Core.Binary;
+
+    /// <summary>
+    /// Reader extensions.
+    /// </summary>
+    internal static class BinaryReaderExtensions
+    {
+        /// <summary>
+        /// Reads untyped collection as a generic list.
+        /// </summary>
+        /// <typeparam name="T">Type of list element.</typeparam>
+        /// <param name="reader">The reader.</param>
+        /// <returns>Resulting generic list.</returns>
+        public static List<T> ReadCollectionAsList<T>(this IBinaryRawReader reader)
+        {
+            return ((List<T>) reader.ReadCollection(size => new List<T>(size),
+                (col, elem) => ((List<T>) col).Add((T) elem)));
+        }
+
+        /// <summary>
+        /// Reads untyped dictionary as generic dictionary.
+        /// </summary>
+        /// <typeparam name="TKey">The type of the key.</typeparam>
+        /// <typeparam name="TValue">The type of the value.</typeparam>
+        /// <param name="reader">The reader.</param>
+        /// <returns>Resulting dictionary.</returns>
+        public static Dictionary<TKey, TValue> ReadDictionaryAsGeneric<TKey, TValue>(this IBinaryRawReader reader)
+        {
+            return (Dictionary<TKey, TValue>) reader.ReadDictionary(size => new Dictionary<TKey, TValue>(size));
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/894057e5/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryReaderHandleDictionary.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryReaderHandleDictionary.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryReaderHandleDictionary.cs
new file mode 100644
index 0000000..c145e7f
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryReaderHandleDictionary.cs
@@ -0,0 +1,42 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+namespace Apache.Ignite.Core.Impl.Binary
+{
+    /// <summary>
+    /// Object handle dictionary for <see cref="BinaryReader"/>.
+    /// </summary>
+    internal class BinaryReaderHandleDictionary : BinaryHandleDictionary<int, object>
+    {
+        /// <summary>
+        /// Constructor with initial key-value pair.
+        /// </summary>
+        /// <param name="key">Key.</param>
+        /// <param name="val">Value.</param>
+        public BinaryReaderHandleDictionary(int key, object val)
+            : base(key, val)
+        {
+            // No-op.
+        }
+
+        /** <inheritdoc /> */
+        protected override int EmptyKey
+        {
+            get { return -1; }
+        }
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/894057e5/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryReflectiveActions.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryReflectiveActions.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryReflectiveActions.cs
new file mode 100644
index 0000000..b229898
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryReflectiveActions.cs
@@ -0,0 +1,440 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+namespace Apache.Ignite.Core.Impl.Binary
+{
+    using System;
+    using System.Collections;
+    using System.Diagnostics;
+    using System.Linq.Expressions;
+    using System.Reflection;
+    using Apache.Ignite.Core.Binary;
+    using Apache.Ignite.Core.Common;
+    using Apache.Ignite.Core.Impl.Common;
+
+    /// <summary>
+    /// Write action delegate.
+    /// </summary>
+    /// <param name="obj">Target object.</param>
+    /// <param name="writer">Writer.</param>
+    internal delegate void BinaryReflectiveWriteAction(object obj, IBinaryWriter writer);
+
+    /// <summary>
+    /// Read action delegate.
+    /// </summary>
+    /// <param name="obj">Target object.</param>
+    /// <param name="reader">Reader.</param>
+    internal delegate void BinaryReflectiveReadAction(object obj, IBinaryReader reader);
+
+    /// <summary>
+    /// Routines for reflective reads and writes.
+    /// </summary>
+    internal static class BinaryReflectiveActions
+    {
+        /** Method: read enum. */
+        private static readonly MethodInfo MthdReadEnum =
+            typeof(IBinaryReader).GetMethod("ReadEnum", new[] { typeof(string) });
+
+        /** Method: read enum array. */
+        private static readonly MethodInfo MthdReadEnumArray =
+            typeof(IBinaryReader).GetMethod("ReadEnumArray", new[] { typeof(string) });
+
+        /** Method: read array. */
+        private static readonly MethodInfo MthdReadObjArray =
+            typeof(IBinaryReader).GetMethod("ReadArray", new[] { typeof(string) });
+
+        /** Method: read object. */
+        private static readonly MethodInfo MthdReadObj=
+            typeof(IBinaryReader).GetMethod("ReadObject", new[] { typeof(string) });
+
+        /** Method: write enum array. */
+        private static readonly MethodInfo MthdWriteEnumArray =
+            typeof(IBinaryWriter).GetMethod("WriteEnumArray");
+
+        /** Method: write array. */
+        private static readonly MethodInfo MthdWriteObjArray =
+            typeof(IBinaryWriter).GetMethod("WriteArray");
+
+        /** Method: read object. */
+        private static readonly MethodInfo MthdWriteObj =
+            typeof(IBinaryWriter).GetMethod("WriteObject");
+
+        /// <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 BinaryReflectiveWriteAction writeAction, 
+            out BinaryReflectiveReadAction 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 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 BinaryReflectiveWriteAction writeAction,
+            out BinaryReflectiveReadAction 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);
+        }
+
+        /// <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 BinaryReflectiveWriteAction writeAction,
+            out BinaryReflectiveReadAction 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.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 BinaryReflectiveWriteAction writeAction,
+            out BinaryReflectiveReadAction 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.ReadObject<Guid>(f));
+            }
+            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.IsEnum)
+            {
+                writeAction = GetWriter<object>(field, (f, w, o) => w.WriteEnum(f, o), true);
+                readAction = GetReader(field, MthdReadEnum);
+            }
+            else if (type == BinaryUtils.TypDictionary || type.GetInterface(BinaryUtils.TypDictionary.FullName) != null && !type.IsGenericType)
+            {
+                writeAction = GetWriter<IDictionary>(field, (f, w, o) => w.WriteDictionary(f, o));
+                readAction = GetReader(field, (f, r) => r.ReadDictionary(f));
+            }
+            else if (type == BinaryUtils.TypCollection || type.GetInterface(BinaryUtils.TypCollection.FullName) != null && !type.IsGenericType)
+            {
+                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>
+        /// Gets the reader with a specified write action.
+        /// </summary>
+        private static BinaryReflectiveWriteAction GetWriter<T>(FieldInfo field,
+            Expression<Action<string, IBinaryWriter, T>> write,
+            bool convertFieldValToObject = false)
+        {
+            Debug.Assert(field != null);
+            Debug.Assert(field.DeclaringType != null);   // non-static
+
+            // Get field value
+            var targetParam = Expression.Parameter(typeof(object));
+            var targetParamConverted = Expression.Convert(targetParam, field.DeclaringType);
+            Expression fldExpr = Expression.Field(targetParamConverted, field);
+
+            if (convertFieldValToObject)
+                fldExpr = Expression.Convert(fldExpr, typeof (object));
+
+            // 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();
+        }
+
+        /// <summary>
+        /// Gets the writer with a specified generic method.
+        /// </summary>
+        private static BinaryReflectiveWriteAction GetWriter(FieldInfo field, MethodInfo method, 
+            params Type[] genericArgs)
+        {
+            Debug.Assert(field != null);
+            Debug.Assert(field.DeclaringType != null);   // non-static
+
+            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 fldNameParam = Expression.Constant(BinaryUtils.CleanFieldName(field.Name));
+            var writeMethod = method.MakeGenericMethod(genericArgs);
+            var writeExpr = Expression.Call(writerParam, writeMethod, fldNameParam, fldExpr);
+
+            // Compile and return
+            return Expression.Lambda<BinaryReflectiveWriteAction>(writeExpr, targetParam, writerParam).Compile();
+        }
+
+        /// <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>
+        /// Gets the reader with a specified generic method.
+        /// </summary>
+        private static BinaryReflectiveReadAction GetReader(FieldInfo field, MethodInfo method, 
+            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 fldNameParam = Expression.Constant(BinaryUtils.CleanFieldName(field.Name));
+            var readMethod = method.MakeGenericMethod(genericArgs);
+            Expression readExpr = Expression.Call(readerParam, readMethod, fldNameParam);
+
+            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, field.DeclaringType);
+            var assignExpr = Expression.Call(DelegateConverter.GetWriteFieldMethod(field), targetParamConverted, 
+                readExpr);
+
+            // Compile and return
+            return Expression.Lambda<BinaryReflectiveReadAction>(assignExpr, targetParam, readerParam).Compile();
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/894057e5/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryReflectiveSerializer.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryReflectiveSerializer.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryReflectiveSerializer.cs
new file mode 100644
index 0000000..0804c25
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryReflectiveSerializer.cs
@@ -0,0 +1,218 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+namespace Apache.Ignite.Core.Impl.Binary
+{
+    using System;
+    using System.Collections.Generic;
+    using System.Reflection;
+    using Apache.Ignite.Core.Binary;
+
+    /// <summary>
+    /// Binary serializer which reflectively writes all fields except of ones with 
+    /// <see cref="System.NonSerializedAttribute"/>.
+    /// <para />
+    /// Note that Java platform stores dates as a difference between current time 
+    /// and predefined absolute UTC date. Therefore, this difference is always the 
+    /// same for all time zones. .Net, in contrast, stores dates as a difference 
+    /// between current time and some predefined date relative to the current time 
+    /// zone. It means that this difference will be different as you change time zones. 
+    /// To overcome this discrepancy Ignite always converts .Net date to UTC form 
+    /// before serializing and allows user to decide whether to deserialize them 
+    /// in UTC or local form using <c>ReadTimestamp(..., true/false)</c> methods in 
+    /// <see cref="IBinaryReader"/> and <see cref="IBinaryRawReader"/>.
+    /// This serializer always read dates in UTC form. It means that if you have
+    /// local date in any field/property, it will be implicitly converted to UTC
+    /// form after the first serialization-deserialization cycle. 
+    /// </summary>
+    internal class BinaryReflectiveSerializer : IBinarySerializer
+    {
+        /** Cached binding flags. */
+        private static readonly BindingFlags Flags = BindingFlags.Instance | BindingFlags.Public |
+            BindingFlags.NonPublic | BindingFlags.DeclaredOnly;
+
+        /** Cached type descriptors. */
+        private readonly IDictionary<Type, Descriptor> _types = new Dictionary<Type, Descriptor>();
+
+        /// <summary>
+        /// Write portalbe object.
+        /// </summary>
+        /// <param name="obj">Object.</param>
+        /// <param name="writer">Writer.</param>
+        /// <exception cref="BinaryObjectException">Type is not registered in serializer:  + type.Name</exception>
+        public void WriteBinary(object obj, IBinaryWriter writer)
+        {
+            var binarizable = obj as IBinarizable;
+
+            if (binarizable != null)
+                binarizable.WriteBinary(writer);
+            else
+                GetDescriptor(obj).Write(obj, writer);
+        }
+
+        /// <summary>
+        /// Read binary object.
+        /// </summary>
+        /// <param name="obj">Instantiated empty object.</param>
+        /// <param name="reader">Reader.</param>
+        /// <exception cref="BinaryObjectException">Type is not registered in serializer:  + type.Name</exception>
+        public void ReadBinary(object obj, IBinaryReader reader)
+        {
+            var binarizable = obj as IBinarizable;
+            
+            if (binarizable != null)
+                binarizable.ReadBinary(reader);
+            else
+                GetDescriptor(obj).Read(obj, reader);
+        }
+
+        /// <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>
+        /// Gets the descriptor for an object.
+        /// </summary>
+        private Descriptor GetDescriptor(object obj)
+        {
+            var type = obj.GetType();
+
+            Descriptor desc;
+
+            if (!_types.TryGetValue(type, out desc))
+                throw new BinaryObjectException("Type is not registered in serializer: " + type.Name);
+
+            return desc;
+        }
+        
+        /// <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);
+        }
+
+        /// <summary>
+        /// Type descriptor. 
+        /// </summary>
+        private class Descriptor
+        {
+            /** Write actions to be performed. */
+            private readonly List<BinaryReflectiveWriteAction> _wActions;
+
+            /** Read actions to be performed. */
+            private readonly List<BinaryReflectiveReadAction> _rActions;
+
+            /// <summary>
+            /// Constructor.
+            /// </summary>
+            /// <param name="fields">Fields.</param>
+            public Descriptor(List<FieldInfo> fields)
+            {
+                _wActions = new List<BinaryReflectiveWriteAction>(fields.Count);
+                _rActions = new List<BinaryReflectiveReadAction>(fields.Count);
+
+                foreach (FieldInfo field in fields)
+                {
+                    BinaryReflectiveWriteAction writeAction;
+                    BinaryReflectiveReadAction readAction;
+
+                    BinaryReflectiveActions.TypeActions(field, out writeAction, out readAction);
+
+                    _wActions.Add(writeAction);
+                    _rActions.Add(readAction);
+                }
+            }
+
+            /// <summary>
+            /// Write object.
+            /// </summary>
+            /// <param name="obj">Object.</param>
+            /// <param name="writer">Writer.</param>
+            public void Write(object obj, IBinaryWriter writer)
+            {
+                int cnt = _wActions.Count;
+
+                for (int i = 0; i < cnt; i++)
+                    _wActions[i](obj, writer);                   
+            }
+
+            /// <summary>
+            /// Read object.
+            /// </summary>
+            /// <param name="obj">Object.</param>
+            /// <param name="reader">Reader.</param>
+            public void Read(object obj, IBinaryReader reader)
+            {
+                int cnt = _rActions.Count;
+
+                for (int i = 0; i < cnt; i++ )
+                    _rActions[i](obj, reader);
+            }
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/894057e5/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinarySurrogateTypeDescriptor.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinarySurrogateTypeDescriptor.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinarySurrogateTypeDescriptor.cs
new file mode 100644
index 0000000..247b40d
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinarySurrogateTypeDescriptor.cs
@@ -0,0 +1,162 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+namespace Apache.Ignite.Core.Impl.Binary
+{
+    using System;
+    using System.Collections.Generic;
+    using Apache.Ignite.Core.Binary;
+    using Apache.Ignite.Core.Impl.Binary.Structure;
+
+    /// <summary>
+    /// Surrogate type descriptor. Used in cases when type if identified by name and 
+    /// is not provided in configuration.
+    /// </summary>
+    internal class BinarySurrogateTypeDescriptor : IBinaryTypeDescriptor
+    {
+        /** Binary configuration. */
+        private readonly BinaryConfiguration _cfg;
+
+        /** Type ID. */
+        private readonly int _id;
+
+        /** Type name. */
+        private readonly string _name;
+
+        /** Type structure. */
+        private volatile BinaryStructure _writerTypeStruct = BinaryStructure.CreateEmpty();
+
+        /** Type structure. */
+        private BinaryStructure _readerTypeStructure = BinaryStructure.CreateEmpty();
+        
+        /** Type schema. */
+        private readonly BinaryObjectSchema _schema = new BinaryObjectSchema();
+
+        /// <summary>
+        /// Constructor.
+        /// </summary>
+        /// <param name="cfg">Configuration.</param>
+        /// <param name="id">Type ID.</param>
+        public BinarySurrogateTypeDescriptor(BinaryConfiguration cfg, int id)
+        {
+            _cfg = cfg;
+            _id = id;
+        }
+
+        /// <summary>
+        /// Constrcutor.
+        /// </summary>
+        /// <param name="cfg">Configuration.</param>
+        /// <param name="name">Type name.</param>
+        public BinarySurrogateTypeDescriptor(BinaryConfiguration cfg, string name)
+        {
+            _cfg = cfg;
+            _name = name;
+
+            _id = BinaryUtils.TypeId(name, cfg.DefaultNameMapper, cfg.DefaultIdMapper);
+        }
+
+        /** <inheritDoc /> */
+        public Type Type
+        {
+            get { return null; }
+        }
+
+        /** <inheritDoc /> */
+        public int TypeId
+        {
+            get { return _id; }
+        }
+
+        /** <inheritDoc /> */
+        public string TypeName
+        {
+            get { return _name; }
+        }
+
+        /** <inheritDoc /> */
+        public bool UserType
+        {
+            get { return true; }
+        }
+
+        /** <inheritDoc /> */
+        public bool KeepDeserialized
+        {
+            get { return _cfg.DefaultKeepDeserialized; }
+        }
+
+        /** <inheritDoc /> */
+        public IBinaryNameMapper NameMapper
+        {
+            get { return _cfg.DefaultNameMapper; }
+        }
+
+        /** <inheritDoc /> */
+        public IBinaryIdMapper IdMapper
+        {
+            get { return _cfg.DefaultIdMapper; }
+        }
+
+        /** <inheritDoc /> */
+        public IBinarySerializer Serializer
+        {
+            get { return _cfg.DefaultSerializer; }
+        }
+
+        /** <inheritDoc /> */
+        public string AffinityKeyFieldName
+        {
+            get { return null; }
+        }
+
+        /** <inheritDoc /> */
+        public BinaryStructure WriterTypeStructure
+        {
+            get { return _writerTypeStruct; }
+        }
+
+        public BinaryStructure ReaderTypeStructure
+        {
+            get { return _readerTypeStructure; }
+        }
+
+        /** <inheritDoc /> */
+        public void UpdateWriteStructure(BinaryStructure exp, int pathIdx, IList<BinaryStructureUpdate> updates)
+        {
+            lock (this)
+            {
+                _writerTypeStruct = _writerTypeStruct.Merge(exp, pathIdx, updates);
+            }
+        }
+
+        /** <inheritDoc /> */
+        public void UpdateReadStructure(BinaryStructure exp, int pathIdx, IList<BinaryStructureUpdate> updates)
+        {
+            lock (this)
+            {
+                _readerTypeStructure = _readerTypeStructure.Merge(exp, pathIdx, updates);
+            }
+        }
+
+        /** <inheritDoc /> */
+        public BinaryObjectSchema Schema
+        {
+            get { return _schema; }
+        }
+    }
+}


Mime
View raw message