ignite-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From voze...@apache.org
Subject [2/9] ignite git commit: IGNITE-1644: Correct DateTime serialization.
Date Tue, 27 Oct 2015 14:59:31 GMT
IGNITE-1644: Correct DateTime serialization.


Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/05e739f1
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/05e739f1
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/05e739f1

Branch: refs/heads/ignite-1770
Commit: 05e739f1689cd801f669f3a668b5039ca0a7d653
Parents: 9d67c20
Author: Pavel Tupitsyn <ptupitsyn@gridgain.com>
Authored: Tue Oct 27 13:50:29 2015 +0300
Committer: vozerov-gridgain <vozerov@gridgain.com>
Committed: Tue Oct 27 13:50:29 2015 +0300

----------------------------------------------------------------------
 .../Portable/PortableApiSelfTest.cs             |  60 ++-
 .../Portable/PortableSelfTest.cs                |  42 +-
 .../Apache.Ignite.Core.csproj                   |   1 +
 .../Impl/Portable/DateTimeHolder.cs             |  68 +++
 .../Impl/Portable/PortableBuilderField.cs       |  56 ++-
 .../Impl/Portable/PortableBuilderImpl.cs        | 420 ++++++++++++++-----
 .../Impl/Portable/PortableMarshaller.cs         |   1 +
 .../Impl/Portable/PortableReaderImpl.cs         | 148 ++++---
 .../Impl/Portable/PortableReflectiveRoutines.cs |  15 -
 .../Impl/Portable/PortableSystemHandlers.cs     |  94 ++++-
 .../Impl/Portable/PortableUserObject.cs         |  73 ++--
 .../Impl/Portable/PortableUtils.cs              |  19 +-
 .../Impl/Portable/PortableWriterImpl.cs         |  31 +-
 .../Portable/IPortableBuilder.cs                | 235 +++++++++++
 14 files changed, 929 insertions(+), 334 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/05e739f1/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Portable/PortableApiSelfTest.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Portable/PortableApiSelfTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Portable/PortableApiSelfTest.cs
index bb1cf06..c85c823 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Portable/PortableApiSelfTest.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Portable/PortableApiSelfTest.cs
@@ -448,7 +448,7 @@ namespace Apache.Ignite.Core.Tests.Portable
             IPortableBuilder builderItem =
                 _grid.GetPortables().GetBuilder(typeof(BuilderCollectionItem)).SetField("val", 1);
 
-            builderCol.SetField<ICollection>("col", new ArrayList { builderItem });
+            builderCol.SetCollectionField("col", new ArrayList { builderItem });
 
             IPortableObject portCol = builderCol.Build();
 
@@ -801,18 +801,18 @@ namespace Apache.Ignite.Core.Tests.Portable
         [Test]
         public void TestStringDateGuidEnum()
         {
-            DateTime? nDate = DateTime.Now.ToUniversalTime();
+            DateTime? nDate = DateTime.Now;
 
             Guid? nGuid = Guid.NewGuid();
 
             IPortableObject portObj = _grid.GetPortables().GetBuilder(typeof(StringDateGuidEnum))
                 .SetField("fStr", "str")
                 .SetField("fNDate", nDate)
-                .SetField("fNGuid", nGuid)
+                .SetGuidField("fNGuid", nGuid)
                 .SetField("fEnum", TestEnum.One)
                 .SetField("fStrArr", new[] { "str" })
-                .SetField("fDateArr", new[] { nDate })
-                .SetField("fGuidArr", new[] { nGuid })
+                .SetArrayField("fDateArr", new[] { nDate })
+                .SetGuidArrayField("fGuidArr", new[] { nGuid })
                 .SetField("fEnumArr", new[] { TestEnum.One })
                 .SetHashCode(100)
                 .Build();
@@ -826,11 +826,11 @@ namespace Apache.Ignite.Core.Tests.Portable
             Assert.AreEqual(8, meta.Fields.Count);
 
             Assert.AreEqual(PortableTypeNames.TypeNameString, meta.GetFieldTypeName("fStr"));
-            Assert.AreEqual(PortableTypeNames.TypeNameTimestamp, meta.GetFieldTypeName("fNDate"));
+            Assert.AreEqual(PortableTypeNames.TypeNameObject, meta.GetFieldTypeName("fNDate"));
             Assert.AreEqual(PortableTypeNames.TypeNameGuid, meta.GetFieldTypeName("fNGuid"));
             Assert.AreEqual(PortableTypeNames.TypeNameEnum, meta.GetFieldTypeName("fEnum"));
             Assert.AreEqual(PortableTypeNames.TypeNameArrayString, meta.GetFieldTypeName("fStrArr"));
-            Assert.AreEqual(PortableTypeNames.TypeNameArrayTimestamp, meta.GetFieldTypeName("fDateArr"));
+            Assert.AreEqual(PortableTypeNames.TypeNameArrayObject, meta.GetFieldTypeName("fDateArr"));
             Assert.AreEqual(PortableTypeNames.TypeNameArrayGuid, meta.GetFieldTypeName("fGuidArr"));
             Assert.AreEqual(PortableTypeNames.TypeNameArrayEnum, meta.GetFieldTypeName("fEnumArr"));
 
@@ -854,18 +854,52 @@ namespace Apache.Ignite.Core.Tests.Portable
             Assert.AreEqual(new[] { nGuid }, obj.FGuidArr);
             Assert.AreEqual(new[] { TestEnum.One }, obj.FEnumArr);
 
+            // Check builder field caching.
+            var builder = _grid.GetPortables().GetBuilder(portObj);
+
+            Assert.AreEqual("str", builder.GetField<string>("fStr"));
+            Assert.AreEqual(nDate, builder.GetField<DateTime?>("fNDate"));
+            Assert.AreEqual(nGuid, builder.GetField<Guid?>("fNGuid"));
+            Assert.AreEqual(TestEnum.One, builder.GetField<TestEnum>("fEnum"));
+            Assert.AreEqual(new[] { "str" }, builder.GetField<string[]>("fStrArr"));
+            Assert.AreEqual(new[] { nDate }, builder.GetField<DateTime?[]>("fDateArr"));
+            Assert.AreEqual(new[] { nGuid }, builder.GetField<Guid?[]>("fGuidArr"));
+            Assert.AreEqual(new[] { TestEnum.One }, builder.GetField<TestEnum[]>("fEnumArr"));
+
+            // Check reassemble.
+            portObj = builder.Build();
+
+            Assert.AreEqual("str", portObj.GetField<string>("fStr"));
+            Assert.AreEqual(nDate, portObj.GetField<DateTime?>("fNDate"));
+            Assert.AreEqual(nGuid, portObj.GetField<Guid?>("fNGuid"));
+            Assert.AreEqual(TestEnum.One, portObj.GetField<TestEnum>("fEnum"));
+            Assert.AreEqual(new[] { "str" }, portObj.GetField<string[]>("fStrArr"));
+            Assert.AreEqual(new[] { nDate }, portObj.GetField<DateTime?[]>("fDateArr"));
+            Assert.AreEqual(new[] { nGuid }, portObj.GetField<Guid?[]>("fGuidArr"));
+            Assert.AreEqual(new[] { TestEnum.One }, portObj.GetField<TestEnum[]>("fEnumArr"));
+
+            obj = portObj.Deserialize<StringDateGuidEnum>();
+
+            Assert.AreEqual("str", obj.FStr);
+            Assert.AreEqual(nDate, obj.FnDate);
+            Assert.AreEqual(nGuid, obj.FnGuid);
+            Assert.AreEqual(TestEnum.One, obj.FEnum);
+            Assert.AreEqual(new[] { "str" }, obj.FStrArr);
+            Assert.AreEqual(new[] { nDate }, obj.FDateArr);
+            Assert.AreEqual(new[] { nGuid }, obj.FGuidArr);
+            Assert.AreEqual(new[] { TestEnum.One }, obj.FEnumArr);
+
             // Overwrite.
             nDate = DateTime.Now.ToUniversalTime();
-
             nGuid = Guid.NewGuid();
 
-            portObj = _grid.GetPortables().GetBuilder(typeof(StringDateGuidEnum))
+            portObj = builder
                 .SetField("fStr", "str2")
-                .SetField("fNDate", nDate)
+                .SetTimestampField("fNDate", nDate)
                 .SetField("fNGuid", nGuid)
                 .SetField("fEnum", TestEnum.Two)
                 .SetField("fStrArr", new[] { "str2" })
-                .SetField("fDateArr", new[] { nDate })
+                .SetArrayField("fDateArr", new[] { nDate })
                 .SetField("fGuidArr", new[] { nGuid })
                 .SetField("fEnumArr", new[] { TestEnum.Two })
                 .SetHashCode(200)
@@ -1070,8 +1104,8 @@ namespace Apache.Ignite.Core.Tests.Portable
             dict[3] = new CompositeInner(3);
 
             IPortableObject portObj = _grid.GetPortables().GetBuilder(typeof(CompositeContainer)).SetHashCode(100)
-                .SetField<ICollection>("col", col)
-                .SetField("dict", dict).Build();
+                .SetCollectionField("col", col)
+                .SetDictionaryField("dict", dict).Build();
 
             // 1. Check meta.
             IPortableMetadata meta = portObj.GetMetadata();

http://git-wip-us.apache.org/repos/asf/ignite/blob/05e739f1/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Portable/PortableSelfTest.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Portable/PortableSelfTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Portable/PortableSelfTest.cs
index 62d52f6..08e0b31 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Portable/PortableSelfTest.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Portable/PortableSelfTest.cs
@@ -26,7 +26,6 @@ namespace Apache.Ignite.Core.Tests.Portable
     using System.Collections;
     using System.Collections.Generic;
     using System.Linq;
-    using System.Text;
     using Apache.Ignite.Core.Common;
     using Apache.Ignite.Core.Impl.Portable;
     using Apache.Ignite.Core.Impl.Portable.IO;
@@ -529,6 +528,24 @@ namespace Apache.Ignite.Core.Tests.Portable
             Assert.AreEqual(obj.UtcArrRaw, otherObj.UtcArrRaw);
         }
 
+        /// <summary>
+        /// Tests the DateTime marshalling.
+        /// </summary>
+        [Test]
+        public void TestDateTime()
+        {
+            var time = DateTime.Now;
+            Assert.AreEqual(_marsh.Unmarshal<DateTime>(_marsh.Marshal(time)), time);
+
+            var timeUtc = DateTime.UtcNow;
+            Assert.AreEqual(_marsh.Unmarshal<DateTime>(_marsh.Marshal(timeUtc)), timeUtc);
+
+            // Check exception with non-UTC date
+            var stream = new PortableHeapStream(128);
+            var writer = _marsh.StartMarshal(stream);
+            Assert.Throws<InvalidOperationException>(() => writer.WriteTimestamp(DateTime.Now));
+        }
+
         /**
          * <summary>Check generic collections.</summary>
          */
@@ -1396,29 +1413,6 @@ namespace Apache.Ignite.Core.Tests.Portable
             }
         }
 
-        private static string CollectionAsString(ICollection col)
-        {
-            if (col == null)
-                return null;
-            StringBuilder sb = new StringBuilder("[");
-
-            bool first = true;
-
-            foreach (object elem in col)
-            {
-                if (first)
-                    first = false;
-                else
-                    sb.Append(", ");
-
-                sb.Append(elem);
-            }
-
-            sb.Append("]");
-
-            return sb.ToString();
-        }
-
         public class TestList : ArrayList
         {
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/05e739f1/modules/platforms/dotnet/Apache.Ignite.Core/Apache.Ignite.Core.csproj
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Apache.Ignite.Core.csproj b/modules/platforms/dotnet/Apache.Ignite.Core/Apache.Ignite.Core.csproj
index f314c99..04cbca1 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Apache.Ignite.Core.csproj
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Apache.Ignite.Core.csproj
@@ -243,6 +243,7 @@
     <Compile Include="Impl\Messaging\Messaging.cs" />
     <Compile Include="Impl\Messaging\MessagingAsync.cs" />
     <Compile Include="Impl\NativeMethods.cs" />
+    <Compile Include="Impl\Portable\DateTimeHolder.cs" />
     <Compile Include="Impl\Portable\IO\IPortableStream.cs" />
     <Compile Include="Impl\Portable\IO\PortableAbstractStream.cs" />
     <Compile Include="Impl\Portable\IO\PortableHeapStream.cs" />

http://git-wip-us.apache.org/repos/asf/ignite/blob/05e739f1/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Portable/DateTimeHolder.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Portable/DateTimeHolder.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Portable/DateTimeHolder.cs
new file mode 100644
index 0000000..9c232a0
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Portable/DateTimeHolder.cs
@@ -0,0 +1,68 @@
+/*
+ * 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.Portable
+{
+    using System;
+    using System.Diagnostics;
+    using Apache.Ignite.Core.Portable;
+
+    /// <summary>
+    /// Wraps Serializable item in a portable.
+    /// </summary>
+    internal class DateTimeHolder : IPortableWriteAware
+    {
+        /** */
+        private readonly DateTime _item;
+
+        /// <summary>
+        /// Constructor.
+        /// </summary>
+        /// <param name="item">The item to wrap.</param>
+        public DateTimeHolder(DateTime item)
+        {
+            _item = item;
+        }
+
+        /// <summary>
+        /// Constructor.
+        /// </summary>
+        /// <param name="reader">The reader.</param>
+        public DateTimeHolder(IPortableReader reader)
+        {
+            Debug.Assert(reader != null);
+
+            _item = DateTime.FromBinary(reader.GetRawReader().ReadLong());
+        }
+
+        /// <summary>
+        /// Gets the item to wrap.
+        /// </summary>
+        public DateTime Item
+        {
+            get { return _item; }
+        }
+
+        /** <inheritDoc /> */
+        public void WritePortable(IPortableWriter writer)
+        {
+            Debug.Assert(writer != null);
+
+            writer.GetRawWriter().WriteLong(_item.ToBinary());
+        }
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/05e739f1/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Portable/PortableBuilderField.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Portable/PortableBuilderField.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Portable/PortableBuilderField.cs
index 026d0d4..c54348d 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Portable/PortableBuilderField.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Portable/PortableBuilderField.cs
@@ -24,28 +24,34 @@ namespace Apache.Ignite.Core.Impl.Portable
     /// </summary>
     internal class PortableBuilderField
     {
-        /** Remove marker object. */
-        public static readonly object RmvMarkerObj = new object();
-
         /** Remove marker. */
-        public static readonly PortableBuilderField RmvMarker = 
-            new PortableBuilderField(null, RmvMarkerObj);
+        public static readonly PortableBuilderField RmvMarker = new PortableBuilderField(null, null, 0);
 
         /** Type. */
-        private readonly Type _typ;
+        private readonly Type _type;
 
         /** Value. */
-        private readonly object _val;
+        private readonly object _value;
+        
+        /** Write action. */
+        private readonly Action<PortableWriterImpl, object> _writeAction;
+        
+        /** Type id. */
+        private readonly byte _typeId;
 
         /// <summary>
         /// Constructor.
         /// </summary>
-        /// <param name="typ">Type.</param>
-        /// <param name="val">Value.</param>
-        public PortableBuilderField(Type typ, object val)
+        /// <param name="type">Type.</param>
+        /// <param name="value">Value.</param>
+        /// <param name="typeId">The type identifier.</param>
+        /// <param name="writeAction">Optional write action.</param>
+        public PortableBuilderField(Type type, object value, byte typeId, Action<PortableWriterImpl, object> writeAction = null)
         {
-            _typ = typ;
-            _val = val;
+            _type = type;
+            _value = value;
+            _typeId = typeId;
+            _writeAction = writeAction;
         }
 
         /// <summary>
@@ -53,10 +59,7 @@ namespace Apache.Ignite.Core.Impl.Portable
         /// </summary>
         public Type Type
         {
-            get
-            {
-                return _typ;
-            }
+            get { return _type; }
         }
 
         /// <summary>
@@ -64,10 +67,23 @@ namespace Apache.Ignite.Core.Impl.Portable
         /// </summary>
         public object Value
         {
-            get
-            {
-                return _val;
-            }
+            get { return _value; }
+        }
+
+        /// <summary>
+        /// Gets the write action.
+        /// </summary>
+        public Action<PortableWriterImpl, object> WriteAction
+        {
+            get { return _writeAction; }
+        }
+
+        /// <summary>
+        /// Gets the type identifier.
+        /// </summary>
+        public byte TypeId
+        {
+            get { return _typeId; }
         }
     }
 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/05e739f1/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Portable/PortableBuilderImpl.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Portable/PortableBuilderImpl.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Portable/PortableBuilderImpl.cs
index ac7a957..9767037 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Portable/PortableBuilderImpl.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Portable/PortableBuilderImpl.cs
@@ -20,7 +20,7 @@ namespace Apache.Ignite.Core.Impl.Portable
     using System;
     using System.Collections;
     using System.Collections.Generic;
-    using System.Diagnostics.CodeAnalysis;
+    using System.Diagnostics;
     using System.IO;
     using Apache.Ignite.Core.Common;
     using Apache.Ignite.Core.Impl.Portable.IO;
@@ -32,11 +32,9 @@ namespace Apache.Ignite.Core.Impl.Portable
     /// </summary>
     internal class PortableBuilderImpl : IPortableBuilder
     {
-        /** Type IDs for metadata. */
-        private static readonly IDictionary<Type, int> TypeIds;
-
         /** Cached dictionary with no values. */
-        private static readonly IDictionary<int, object> EmptyVals = new Dictionary<int, object>();
+        private static readonly IDictionary<int, PortableBuilderField> EmptyVals =
+            new Dictionary<int, PortableBuilderField>();
         
         /** Portables. */
         private readonly PortablesImpl _portables;
@@ -54,55 +52,29 @@ namespace Apache.Ignite.Core.Impl.Portable
         private IDictionary<string, PortableBuilderField> _vals;
 
         /** Contextual fields. */
-        private IDictionary<int, object> _cache;
+        private IDictionary<int, PortableBuilderField> _cache;
 
         /** Hash code. */
         private int _hashCode;
         
         /** Current context. */
         private Context _ctx;
-        
-        /// <summary>
-        /// Static initializer.
-        /// </summary>
-        [SuppressMessage("Microsoft.Performance", "CA1810:InitializeReferenceTypeStaticFieldsInline")]
-        static PortableBuilderImpl()
-        {
-            TypeIds = new Dictionary<Type, int>();
-
-            // 1. Primitives.
-            TypeIds[typeof(byte)] = PortableUtils.TypeByte;
-            TypeIds[typeof(bool)] = PortableUtils.TypeBool;
-            TypeIds[typeof(short)] = PortableUtils.TypeShort;
-            TypeIds[typeof(char)] = PortableUtils.TypeChar;
-            TypeIds[typeof(int)] = PortableUtils.TypeInt;
-            TypeIds[typeof(long)] = PortableUtils.TypeLong;
-            TypeIds[typeof(float)] = PortableUtils.TypeFloat;
-            TypeIds[typeof(double)] = PortableUtils.TypeDouble;
-            TypeIds[typeof(decimal)] = PortableUtils.TypeDecimal;
-
-            TypeIds[typeof(byte[])] = PortableUtils.TypeArrayByte;
-            TypeIds[typeof(bool[])] = PortableUtils.TypeArrayBool;
-            TypeIds[typeof(short[])] = PortableUtils.TypeArrayShort;
-            TypeIds[typeof(char[])] = PortableUtils.TypeArrayChar;
-            TypeIds[typeof(int[])] = PortableUtils.TypeArrayInt;
-            TypeIds[typeof(long[])] = PortableUtils.TypeArrayLong;
-            TypeIds[typeof(float[])] = PortableUtils.TypeArrayFloat;
-            TypeIds[typeof(double[])] = PortableUtils.TypeArrayDouble;
-            TypeIds[typeof(decimal?[])] = PortableUtils.TypeArrayDecimal;
-
-            // 2. String.
-            TypeIds[typeof(string)] = PortableUtils.TypeString;
-            TypeIds[typeof(string[])] = PortableUtils.TypeArrayString;
-
-            // 3. Guid.
-            TypeIds[typeof(Guid?)] = PortableUtils.TypeGuid;
-            TypeIds[typeof(Guid?[])] = PortableUtils.TypeArrayGuid;
-
-            // 4. Date.
-            TypeIds[typeof(DateTime?)] = PortableUtils.TypeTimestamp;
-            TypeIds[typeof(DateTime?[])] = PortableUtils.TypeArrayTimestamp;
-        }
+
+        /** Write array action. */
+        private static readonly Action<PortableWriterImpl, object> WriteArrayAction = 
+            (w, o) => w.WriteArrayInternal((Array) o);
+
+        /** Write collection action. */
+        private static readonly Action<PortableWriterImpl, object> WriteCollectionAction = 
+            (w, o) => w.WriteCollection((ICollection) o);
+
+        /** Write timestamp action. */
+        private static readonly Action<PortableWriterImpl, object> WriteTimestampAction = 
+            (w, o) => w.WriteTimestamp((DateTime?) o);
+
+        /** Write timestamp array action. */
+        private static readonly Action<PortableWriterImpl, object> WriteTimestampArrayAction = 
+            (w, o) => w.WriteTimestampArray((DateTime?[])o);
 
         /// <summary>
         /// Constructor.
@@ -114,6 +86,10 @@ namespace Apache.Ignite.Core.Impl.Portable
         public PortableBuilderImpl(PortablesImpl portables, PortableBuilderImpl parent, 
             PortableUserObject obj, IPortableTypeDescriptor desc)
         {
+            Debug.Assert(portables != null);
+            Debug.Assert(obj != null);
+            Debug.Assert(desc != null);
+
             _portables = portables;
             _parent = parent ?? this;
             _obj = obj;
@@ -136,22 +112,236 @@ namespace Apache.Ignite.Core.Impl.Portable
             PortableBuilderField field;
 
             if (_vals != null && _vals.TryGetValue(name, out field))
-                return field != PortableBuilderField.RmvMarker ? (T)field.Value : default(T);
-            T val = _obj.Field<T>(name, this);
+                return field != PortableBuilderField.RmvMarker ? (T) field.Value : default(T);
 
-            if (_vals == null)
-                _vals = new Dictionary<string, PortableBuilderField>(2);
+            int pos;
+
+            if (!_obj.TryGetFieldPosition(name, out pos))
+                return default(T);
+
+            T val;
+
+            if (TryGetCachedField(pos, out val))
+                return val;
 
-            _vals[name] = new PortableBuilderField(typeof(T), val);
+            val = _obj.GetField<T>(pos, this);
+
+            var fld = CacheField(pos, val);
+
+            SetField0(name, fld);
 
             return val;
         }
 
         /** <inheritDoc /> */
-        public IPortableBuilder SetField<T>(string name, T val)
+        public IPortableBuilder SetField<T>(string fieldName, T val)
+        {
+            return SetField0(fieldName,
+                new PortableBuilderField(typeof (T), val, PortableSystemHandlers.GetTypeId(typeof (T))));
+        }
+
+        /** <inheritDoc /> */
+        public IPortableBuilder SetArrayField<T>(string fieldName, T[] val)
+        {
+            return SetField0(fieldName,
+                new PortableBuilderField(typeof (T[]), val, PortableUtils.TypeArray, WriteArrayAction));
+        }
+ 
+        /** <inheritDoc /> */
+        public IPortableBuilder SetBooleanField(string fieldName, bool val)
+        {
+            return SetField0(fieldName, new PortableBuilderField(typeof (bool), val, PortableUtils.TypeBool, 
+                (w, o) => w.WriteBoolean((bool) o)));
+        }
+ 
+        /** <inheritDoc /> */
+        public IPortableBuilder SetBooleanArrayField(string fieldName, bool[] val)
+        {
+            return SetField0(fieldName, new PortableBuilderField(typeof (bool[]), val, PortableUtils.TypeArrayBool,
+                (w, o) => w.WriteBooleanArray((bool[]) o)));
+        }
+ 
+        /** <inheritDoc /> */
+        public IPortableBuilder SetByteField(string fieldName, byte val)
+        {
+            return SetField0(fieldName, new PortableBuilderField(typeof (byte), val, PortableUtils.TypeByte,
+                (w, o) => w.WriteByte((byte) o)));
+        }
+ 
+        /** <inheritDoc /> */
+        public IPortableBuilder SetByteArrayField(string fieldName, byte[] val)
+        {
+            return SetField0(fieldName, new PortableBuilderField(typeof (byte[]), val, PortableUtils.TypeArrayByte,
+                (w, o) => w.WriteByteArray((byte[]) o)));
+        }
+ 
+        /** <inheritDoc /> */
+        public IPortableBuilder SetCharField(string fieldName, char val)
+        {
+            return SetField0(fieldName, new PortableBuilderField(typeof (char), val, PortableUtils.TypeChar,
+                (w, o) => w.WriteChar((char) o)));
+        }
+ 
+        /** <inheritDoc /> */
+        public IPortableBuilder SetCharArrayField(string fieldName, char[] val)
+        {
+            return SetField0(fieldName, new PortableBuilderField(typeof (char[]), val, PortableUtils.TypeArrayChar,
+                (w, o) => w.WriteCharArray((char[]) o)));
+        }
+ 
+        /** <inheritDoc /> */
+        public IPortableBuilder SetCollectionField(string fieldName, ICollection val)
+        {
+            return SetField0(fieldName, new PortableBuilderField(typeof (ICollection), val, PortableUtils.TypeCollection,
+                WriteCollectionAction));
+        }
+ 
+        /** <inheritDoc /> */
+        public IPortableBuilder SetDecimalField(string fieldName, decimal? val)
+        {
+            return SetField0(fieldName, new PortableBuilderField(typeof (decimal?), val, PortableUtils.TypeDecimal,
+                (w, o) => w.WriteDecimal((decimal?) o)));
+        }
+ 
+        /** <inheritDoc /> */
+        public IPortableBuilder SetDecimalArrayField(string fieldName, decimal?[] val)
+        {
+            return SetField0(fieldName, new PortableBuilderField(typeof (decimal?[]), val, PortableUtils.TypeArrayDecimal,
+                (w, o) => w.WriteDecimalArray((decimal?[]) o)));
+        }
+ 
+        /** <inheritDoc /> */
+        public IPortableBuilder SetDictionaryField(string fieldName, IDictionary val)
+        {
+            return SetField0(fieldName, new PortableBuilderField(typeof (IDictionary), val, PortableUtils.TypeDictionary,
+                (w, o) => w.WriteDictionary((IDictionary) o)));
+        }
+ 
+        /** <inheritDoc /> */
+        public IPortableBuilder SetDoubleField(string fieldName, double val)
+        {
+            return SetField0(fieldName, new PortableBuilderField(typeof (double), val, PortableUtils.TypeDouble,
+                (w, o) => w.WriteDouble((double) o)));
+        }
+ 
+        /** <inheritDoc /> */
+        public IPortableBuilder SetDoubleArrayField(string fieldName, double[] val)
+        {
+            return SetField0(fieldName, new PortableBuilderField(typeof (double[]), val, PortableUtils.TypeArrayDouble,
+                (w, o) => w.WriteDoubleArray((double[]) o)));
+        }
+ 
+        /** <inheritDoc /> */
+        public IPortableBuilder SetEnumField<T>(string fieldName, T val)
+        {
+            return SetField0(fieldName, new PortableBuilderField(typeof (T), val, PortableUtils.TypeEnum,
+                (w, o) => w.WriteEnum((T) o)));
+        }
+ 
+        /** <inheritDoc /> */
+        public IPortableBuilder SetEnumArrayField<T>(string fieldName, T[] val)
+        {
+            return SetField0(fieldName, new PortableBuilderField(typeof (T[]), val, PortableUtils.TypeArrayEnum,
+                (w, o) => w.WriteEnumArray((T[]) o)));
+        }
+ 
+        /** <inheritDoc /> */
+        public IPortableBuilder SetFloatField(string fieldName, float val)
+        {
+            return SetField0(fieldName, new PortableBuilderField(typeof (float), val, PortableUtils.TypeFloat,
+                (w, o) => w.WriteFloat((float) o)));
+        }
+ 
+        /** <inheritDoc /> */
+        public IPortableBuilder SetFloatArrayField(string fieldName, float[] val)
+        {
+            return SetField0(fieldName, new PortableBuilderField(typeof (float[]), val, PortableUtils.TypeArrayFloat,
+                (w, o) => w.WriteFloatArray((float[]) o)));
+        }
+ 
+        /** <inheritDoc /> */
+        public IPortableBuilder SetGuidField(string fieldName, Guid? val)
+        {
+            return SetField0(fieldName, new PortableBuilderField(typeof (Guid?), val, PortableUtils.TypeGuid,
+                (w, o) => w.WriteGuid((Guid?) o)));
+        }
+ 
+        /** <inheritDoc /> */
+        public IPortableBuilder SetGuidArrayField(string fieldName, Guid?[] val)
+        {
+            return SetField0(fieldName, new PortableBuilderField(typeof (Guid?[]), val, PortableUtils.TypeArrayGuid,
+                (w, o) => w.WriteGuidArray((Guid?[]) o)));
+        }
+ 
+        /** <inheritDoc /> */
+        public IPortableBuilder SetIntField(string fieldName, int val)
+        {
+            return SetField0(fieldName, new PortableBuilderField(typeof (int), val, PortableUtils.TypeInt,
+                (w, o) => w.WriteInt((int) o)));
+        }
+ 
+        /** <inheritDoc /> */
+        public IPortableBuilder SetIntArrayField(string fieldName, int[] val)
         {
-            return SetField0(name, new PortableBuilderField(typeof(T), val));
+            return SetField0(fieldName, new PortableBuilderField(typeof (int[]), val, PortableUtils.TypeArrayInt,
+                (w, o) => w.WriteIntArray((int[]) o)));
         }
+ 
+        /** <inheritDoc /> */
+        public IPortableBuilder SetLongField(string fieldName, long val)
+        {
+            return SetField0(fieldName, new PortableBuilderField(typeof (long), val, PortableUtils.TypeLong,
+                (w, o) => w.WriteLong((long) o)));
+        }
+ 
+        /** <inheritDoc /> */
+        public IPortableBuilder SetLongArrayField(string fieldName, long[] val)
+        {
+            return SetField0(fieldName, new PortableBuilderField(typeof (long[]), val, PortableUtils.TypeArrayLong,
+                (w, o) => w.WriteLongArray((long[]) o)));
+        }
+ 
+        /** <inheritDoc /> */
+        public IPortableBuilder SetShortField(string fieldName, short val)
+        {
+            return SetField0(fieldName, new PortableBuilderField(typeof (short), val, PortableUtils.TypeShort,
+                (w, o) => w.WriteShort((short) o)));
+        }
+ 
+        /** <inheritDoc /> */
+        public IPortableBuilder SetShortArrayField(string fieldName, short[] val)
+        {
+            return SetField0(fieldName, new PortableBuilderField(typeof (short[]), val, PortableUtils.TypeArrayShort,
+                (w, o) => w.WriteShortArray((short[]) o)));
+        }
+ 
+        /** <inheritDoc /> */
+        public IPortableBuilder SetStringField(string fieldName, string val)
+        {
+            return SetField0(fieldName, new PortableBuilderField(typeof (string), val, PortableUtils.TypeString,
+                (w, o) => w.WriteString((string) o)));
+        }
+ 
+        /** <inheritDoc /> */
+        public IPortableBuilder SetStringArrayField(string fieldName, string[] val)
+        {
+            return SetField0(fieldName, new PortableBuilderField(typeof (string[]), val, PortableUtils.TypeArrayString,
+                (w, o) => w.WriteStringArray((string[]) o)));
+        }
+ 
+        /** <inheritDoc /> */
+        public IPortableBuilder SetTimestampField(string fieldName, DateTime? val)
+        {
+            return SetField0(fieldName, new PortableBuilderField(typeof (DateTime?), val, PortableUtils.TypeTimestamp,
+                WriteTimestampAction));
+        }
+ 
+        /** <inheritDoc /> */
+        public IPortableBuilder SetTimestampArrayField(string fieldName, DateTime?[] val)
+        {
+            return SetField0(fieldName, new PortableBuilderField(typeof (DateTime?[]), val, PortableUtils.TypeArrayTimestamp,
+                WriteTimestampArrayAction));
+        } 
 
         /** <inheritDoc /> */
         public IPortableBuilder RemoveField(string name)
@@ -215,15 +405,15 @@ namespace Apache.Ignite.Core.Impl.Portable
         /// <param name="pos">Position.</param>
         /// <param name="val">Value.</param>
         /// <returns><c>true</c> if value is found in cache.</returns>
-        public bool CachedField<T>(int pos, out T val)
+        public bool TryGetCachedField<T>(int pos, out T val)
         {
             if (_parent._cache != null)
             {
-                object res;
+                PortableBuilderField res;
 
                 if (_parent._cache.TryGetValue(pos, out res))
                 {
-                    val = res != null ? (T)res : default(T);
+                    val = res != null ? (T) res.Value : default(T);
 
                     return true;
                 }
@@ -239,12 +429,46 @@ namespace Apache.Ignite.Core.Impl.Portable
         /// </summary>
         /// <param name="pos">Position.</param>
         /// <param name="val">Value.</param>
-        public void CacheField(int pos, object val)
+        public PortableBuilderField CacheField<T>(int pos, T val)
         {
             if (_parent._cache == null)
-                _parent._cache = new Dictionary<int, object>(2);
+                _parent._cache = new Dictionary<int, PortableBuilderField>(2);
+
+            var hdr = _obj.Data[pos];
+
+            var field = new PortableBuilderField(typeof(T), val, hdr, GetWriteAction(hdr));
+            
+            _parent._cache[pos] = field;
+
+            return field;
+        }
+
+        /// <summary>
+        /// Gets the write action by header.
+        /// </summary>
+        /// <param name="header">The header.</param>
+        /// <returns>Write action.</returns>
+        private static Action<PortableWriterImpl, object> GetWriteAction(byte header)
+        {
+            // We need special actions for all cases where SetField(X) produces different result from SetSpecialField(X)
+            // Arrays, Collections, Dates
+
+            switch (header)
+            {
+                case PortableUtils.TypeArray:
+                    return WriteArrayAction;
+
+                case PortableUtils.TypeCollection:
+                    return WriteCollectionAction;
+
+                case PortableUtils.TypeTimestamp:
+                    return WriteTimestampAction;
 
-            _parent._cache[pos] = val;
+                case PortableUtils.TypeArrayTimestamp:
+                    return WriteTimestampArrayAction;
+            }
+
+            return null;
         }
 
         /// <summary>
@@ -271,7 +495,7 @@ namespace Apache.Ignite.Core.Impl.Portable
         /// <param name="desc">Portable type descriptor.</param>
         /// <param name="hashCode">Hash code.</param>
         /// <param name="vals">Values.</param>
-        internal void Mutate(
+        private void Mutate(
             PortableHeapStream inStream,
             PortableHeapStream outStream,
             IPortableTypeDescriptor desc,
@@ -288,13 +512,13 @@ namespace Apache.Ignite.Core.Impl.Portable
                 // Prepare fields.
                 IPortableMetadataHandler metaHnd = _portables.Marshaller.GetMetadataHandler(desc);
 
-                IDictionary<int, object> vals0;
+                IDictionary<int, PortableBuilderField> vals0;
 
                 if (vals == null || vals.Count == 0)
                     vals0 = EmptyVals;
                 else
                 {
-                    vals0 = new Dictionary<int, object>(vals.Count);
+                    vals0 = new Dictionary<int, PortableBuilderField>(vals.Count);
 
                     foreach (KeyValuePair<string, PortableBuilderField> valEntry in vals)
                     {
@@ -304,12 +528,12 @@ namespace Apache.Ignite.Core.Impl.Portable
                             throw new IgniteException("Collision in field ID detected (change field name or " +
                                 "define custom ID mapper) [fieldName=" + valEntry.Key + ", fieldId=" + fieldId + ']');
 
-                        vals0[fieldId] = valEntry.Value.Value;
+                        vals0[fieldId] = valEntry.Value;
 
                         // Write metadata if: 1) it is enabled for type; 2) type is not null (i.e. it is neither 
                         // remove marker, nor a field read through "GetField" method.
                         if (metaHnd != null && valEntry.Value.Type != null)
-                            metaHnd.OnFieldWrite(fieldId, valEntry.Key, GetTypeId(valEntry.Value.Type));
+                            metaHnd.OnFieldWrite(fieldId, valEntry.Key, valEntry.Value.TypeId);
                     }
                 }
 
@@ -345,7 +569,7 @@ namespace Apache.Ignite.Core.Impl.Portable
         /// <param name="vals">Values to be replaced.</param>
         /// <returns>Mutated object.</returns>
         private void Mutate0(Context ctx, PortableHeapStream inStream, IPortableStream outStream,
-            bool changeHash, int hash, IDictionary<int, object> vals)
+            bool changeHash, int hash, IDictionary<int, PortableBuilderField> vals)
         {
             int inStartPos = inStream.Position;
             int outStartPos = outStream.Position;
@@ -394,10 +618,10 @@ namespace Apache.Ignite.Core.Impl.Portable
                 if (ctx.AddOldToNew(inStartPos, outStartPos, out hndPos))
                 {
                     // Object could be cached in parent builder.
-                    object cachedVal;
+                    PortableBuilderField cachedVal;
 
                     if (_parent._cache != null && _parent._cache.TryGetValue(inStartPos, out cachedVal)) {
-                        ctx.Writer.Write(cachedVal);
+                        WriteField(ctx, cachedVal);
                     }
                     else
                     {
@@ -418,11 +642,11 @@ namespace Apache.Ignite.Core.Impl.Portable
                             int inFieldLen = inStream.ReadInt();
                             int inFieldDataPos = inStream.Position;
 
-                            object fieldVal;
+                            PortableBuilderField fieldVal;
 
                             bool fieldFound = vals.TryGetValue(inFieldId, out fieldVal);
 
-                            if (!fieldFound || fieldVal != PortableBuilderField.RmvMarkerObj)
+                            if (!fieldFound || fieldVal != PortableBuilderField.RmvMarker)
                             {
                                 outStream.WriteInt(inFieldId);
 
@@ -433,8 +657,8 @@ namespace Apache.Ignite.Core.Impl.Portable
                                 if (fieldFound)
                                 {
                                     // Replace field with new value.
-                                    if (fieldVal != PortableBuilderField.RmvMarkerObj)
-                                        ctx.Writer.Write(fieldVal);
+                                    if (fieldVal != PortableBuilderField.RmvMarker)
+                                        WriteField(ctx, fieldVal);
 
                                     vals.Remove(inFieldId);
                                 }
@@ -442,9 +666,9 @@ namespace Apache.Ignite.Core.Impl.Portable
                                 {
                                     // If field was requested earlier, then we must write tracked value
                                     if (_parent._cache != null && _parent._cache.TryGetValue(inFieldDataPos, out fieldVal))
-                                        ctx.Writer.Write(fieldVal);
+                                        WriteField(ctx, fieldVal);
                                     else
-                                        // Filed is not tracked, re-write as is.
+                                        // Field is not tracked, re-write as is.
                                         Mutate0(ctx, inStream, outStream, false, 0, EmptyVals);                                    
                                 }
 
@@ -460,9 +684,9 @@ namespace Apache.Ignite.Core.Impl.Portable
                         }
 
                         // Write remaining new fields.
-                        foreach (KeyValuePair<int, object> valEntry in vals)
+                        foreach (var valEntry in vals)
                         {
-                            if (valEntry.Value != PortableBuilderField.RmvMarkerObj)
+                            if (valEntry.Value != PortableBuilderField.RmvMarker)
                             {
                                 outStream.WriteInt(valEntry.Key);
 
@@ -470,7 +694,7 @@ namespace Apache.Ignite.Core.Impl.Portable
 
                                 outStream.Seek(4, SeekOrigin.Current);
 
-                                ctx.Writer.Write(valEntry.Value);
+                                WriteField(ctx, valEntry.Value);
 
                                 int fieldEndPos = outStream.Position;
 
@@ -518,6 +742,19 @@ namespace Apache.Ignite.Core.Impl.Portable
         }
 
         /// <summary>
+        /// Writes the specified field.
+        /// </summary>
+        private static void WriteField(Context ctx, PortableBuilderField field)
+        {
+            var action = field.WriteAction;
+
+            if (action != null)
+                action(ctx.Writer, field.Value);
+            else
+                ctx.Writer.Write(field.Value);
+        }
+
+        /// <summary>
         /// Process portable object inverting handles if needed.
         /// </summary>
         /// <param name="outStream">Output stream.</param>
@@ -740,33 +977,6 @@ namespace Apache.Ignite.Core.Impl.Portable
         }
 
         /// <summary>
-        /// Get's metadata field type ID for the given type.
-        /// </summary>
-        /// <param name="type">Type.</param>
-        /// <returns>Type ID.</returns>
-        private static int GetTypeId(Type type)
-        {
-            int typeId;
-
-            if (TypeIds.TryGetValue(type, out typeId))
-                return typeId;
-
-            if (type.IsEnum)
-                return PortableUtils.TypeEnum;
-
-            if (type.IsArray)
-                return type.GetElementType().IsEnum ? PortableUtils.TypeArrayEnum : PortableUtils.TypeArray;
-
-            if (typeof (IDictionary).IsAssignableFrom(type))
-                return PortableUtils.TypeDictionary;
-            
-            if (typeof (ICollection).IsAssignableFrom(type))
-                return PortableUtils.TypeCollection;
-
-            return PortableUtils.TypeObject;
-        }
-
-        /// <summary>
         /// Transfer bytes from one stream to another.
         /// </summary>
         /// <param name="inStream">Input stream.</param>

http://git-wip-us.apache.org/repos/asf/ignite/blob/05e739f1/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Portable/PortableMarshaller.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Portable/PortableMarshaller.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Portable/PortableMarshaller.cs
index 2848df1..a8d7058 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Portable/PortableMarshaller.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Portable/PortableMarshaller.cs
@@ -512,6 +512,7 @@ namespace Apache.Ignite.Core.Impl.Portable
             AddSystemType(PortableUtils.TypeComputeActionJob, w => new ComputeActionJob(w));
             AddSystemType(PortableUtils.TypeContinuousQueryRemoteFilterHolder, w => new ContinuousQueryFilterHolder(w));
             AddSystemType(PortableUtils.TypeSerializableHolder, w => new SerializableObjectHolder(w));
+            AddSystemType(PortableUtils.TypeDateTimeHolder, w => new DateTimeHolder(w));
             AddSystemType(PortableUtils.TypeCacheEntryProcessorHolder, w => new CacheEntryProcessorHolder(w));
             AddSystemType(PortableUtils.TypeCacheEntryPredicateHolder, w => new CacheEntryFilterHolder(w));
             AddSystemType(PortableUtils.TypeMessageListenerHolder, w => new MessageListenerHolder(w));

http://git-wip-us.apache.org/repos/asf/ignite/blob/05e739f1/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Portable/PortableReaderImpl.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Portable/PortableReaderImpl.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Portable/PortableReaderImpl.cs
index 2d50499..422d628 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Portable/PortableReaderImpl.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Portable/PortableReaderImpl.cs
@@ -109,7 +109,7 @@ namespace Apache.Ignite.Core.Impl.Portable
         /** <inheritdoc /> */
         public bool ReadBoolean(string fieldName)
         {
-            return ReadField(fieldName, r => r.ReadBoolean());
+            return ReadField(fieldName, r => r.ReadBoolean(), PortableUtils.TypeBool);
         }
 
         /** <inheritdoc /> */
@@ -121,19 +121,19 @@ namespace Apache.Ignite.Core.Impl.Portable
         /** <inheritdoc /> */
         public bool[] ReadBooleanArray(string fieldName)
         {
-            return ReadField(fieldName, PortableUtils.ReadBooleanArray);
+            return ReadField(fieldName, PortableUtils.ReadBooleanArray, PortableUtils.TypeArrayBool);
         }
 
         /** <inheritdoc /> */
         public bool[] ReadBooleanArray()
         {
-            return Read(PortableUtils.ReadBooleanArray);
+            return Read(PortableUtils.ReadBooleanArray, PortableUtils.TypeArrayBool);
         }
 
         /** <inheritdoc /> */
         public byte ReadByte(string fieldName)
         {
-            return ReadField(fieldName, ReadByte);
+            return ReadField(fieldName, ReadByte, PortableUtils.TypeByte);
         }
 
         /** <inheritdoc /> */
@@ -145,19 +145,19 @@ namespace Apache.Ignite.Core.Impl.Portable
         /** <inheritdoc /> */
         public byte[] ReadByteArray(string fieldName)
         {
-            return ReadField(fieldName, PortableUtils.ReadByteArray);
+            return ReadField(fieldName, PortableUtils.ReadByteArray, PortableUtils.TypeArrayByte);
         }
 
         /** <inheritdoc /> */
         public byte[] ReadByteArray()
         {
-            return Read(PortableUtils.ReadByteArray);
+            return Read(PortableUtils.ReadByteArray, PortableUtils.TypeArrayByte);
         }
 
         /** <inheritdoc /> */
         public short ReadShort(string fieldName)
         {
-            return ReadField(fieldName, ReadShort);
+            return ReadField(fieldName, ReadShort, PortableUtils.TypeShort);
         }
 
         /** <inheritdoc /> */
@@ -169,19 +169,19 @@ namespace Apache.Ignite.Core.Impl.Portable
         /** <inheritdoc /> */
         public short[] ReadShortArray(string fieldName)
         {
-            return ReadField(fieldName, PortableUtils.ReadShortArray);
+            return ReadField(fieldName, PortableUtils.ReadShortArray, PortableUtils.TypeArrayShort);
         }
 
         /** <inheritdoc /> */
         public short[] ReadShortArray()
         {
-            return Read(PortableUtils.ReadShortArray);
+            return Read(PortableUtils.ReadShortArray, PortableUtils.TypeArrayShort);
         }
 
         /** <inheritdoc /> */
         public char ReadChar(string fieldName)
         {
-            return ReadField(fieldName, ReadChar);
+            return ReadField(fieldName, ReadChar, PortableUtils.TypeChar);
         }
 
         /** <inheritdoc /> */
@@ -193,19 +193,19 @@ namespace Apache.Ignite.Core.Impl.Portable
         /** <inheritdoc /> */
         public char[] ReadCharArray(string fieldName)
         {
-            return ReadField(fieldName, PortableUtils.ReadCharArray);
+            return ReadField(fieldName, PortableUtils.ReadCharArray, PortableUtils.TypeArrayChar);
         }
 
         /** <inheritdoc /> */
         public char[] ReadCharArray()
         {
-            return Read(PortableUtils.ReadCharArray);
+            return Read(PortableUtils.ReadCharArray, PortableUtils.TypeArrayChar);
         }
 
         /** <inheritdoc /> */
         public int ReadInt(string fieldName)
         {
-            return ReadField(fieldName, ReadInt);
+            return ReadField(fieldName, ReadInt, PortableUtils.TypeInt);
         }
 
         /** <inheritdoc /> */
@@ -217,19 +217,19 @@ namespace Apache.Ignite.Core.Impl.Portable
         /** <inheritdoc /> */
         public int[] ReadIntArray(string fieldName)
         {
-            return ReadField(fieldName, PortableUtils.ReadIntArray);
+            return ReadField(fieldName, PortableUtils.ReadIntArray, PortableUtils.TypeArrayInt);
         }
 
         /** <inheritdoc /> */
         public int[] ReadIntArray()
         {
-            return Read(PortableUtils.ReadIntArray);
+            return Read(PortableUtils.ReadIntArray, PortableUtils.TypeArrayInt);
         }
 
         /** <inheritdoc /> */
         public long ReadLong(string fieldName)
         {
-            return ReadField(fieldName, ReadLong);
+            return ReadField(fieldName, ReadLong, PortableUtils.TypeLong);
         }
 
         /** <inheritdoc /> */
@@ -241,19 +241,19 @@ namespace Apache.Ignite.Core.Impl.Portable
         /** <inheritdoc /> */
         public long[] ReadLongArray(string fieldName)
         {
-            return ReadField(fieldName, PortableUtils.ReadLongArray);
+            return ReadField(fieldName, PortableUtils.ReadLongArray, PortableUtils.TypeArrayLong);
         }
 
         /** <inheritdoc /> */
         public long[] ReadLongArray()
         {
-            return Read(PortableUtils.ReadLongArray);
+            return Read(PortableUtils.ReadLongArray, PortableUtils.TypeArrayLong);
         }
 
         /** <inheritdoc /> */
         public float ReadFloat(string fieldName)
         {
-            return ReadField(fieldName, ReadFloat);
+            return ReadField(fieldName, ReadFloat, PortableUtils.TypeFloat);
         }
 
         /** <inheritdoc /> */
@@ -265,19 +265,19 @@ namespace Apache.Ignite.Core.Impl.Portable
         /** <inheritdoc /> */
         public float[] ReadFloatArray(string fieldName)
         {
-            return ReadField(fieldName, PortableUtils.ReadFloatArray);
+            return ReadField(fieldName, PortableUtils.ReadFloatArray, PortableUtils.TypeArrayFloat);
         }
 
         /** <inheritdoc /> */
         public float[] ReadFloatArray()
         {
-            return Read(PortableUtils.ReadFloatArray);
+            return Read(PortableUtils.ReadFloatArray, PortableUtils.TypeArrayFloat);
         }
 
         /** <inheritdoc /> */
         public double ReadDouble(string fieldName)
         {
-            return ReadField(fieldName, ReadDouble);
+            return ReadField(fieldName, ReadDouble, PortableUtils.TypeDouble);
         }
 
         /** <inheritdoc /> */
@@ -289,133 +289,133 @@ namespace Apache.Ignite.Core.Impl.Portable
         /** <inheritdoc /> */
         public double[] ReadDoubleArray(string fieldName)
         {
-            return ReadField(fieldName, PortableUtils.ReadDoubleArray);
+            return ReadField(fieldName, PortableUtils.ReadDoubleArray, PortableUtils.TypeArrayDouble);
         }
 
         /** <inheritdoc /> */
         public double[] ReadDoubleArray()
         {
-            return Read(PortableUtils.ReadDoubleArray);
+            return Read(PortableUtils.ReadDoubleArray, PortableUtils.TypeArrayDouble);
         }
 
         /** <inheritdoc /> */
         public decimal? ReadDecimal(string fieldName)
         {
-            return ReadField(fieldName, PortableUtils.ReadDecimal);
+            return ReadField(fieldName, PortableUtils.ReadDecimal, PortableUtils.TypeDecimal);
         }
 
         /** <inheritdoc /> */
         public decimal? ReadDecimal()
         {
-            return Read(PortableUtils.ReadDecimal);
+            return Read(PortableUtils.ReadDecimal, PortableUtils.TypeDecimal);
         }
 
         /** <inheritdoc /> */
         public decimal?[] ReadDecimalArray(string fieldName)
         {
-            return ReadField(fieldName, PortableUtils.ReadDecimalArray);
+            return ReadField(fieldName, PortableUtils.ReadDecimalArray, PortableUtils.TypeArrayDecimal);
         }
 
         /** <inheritdoc /> */
         public decimal?[] ReadDecimalArray()
         {
-            return Read(PortableUtils.ReadDecimalArray);
+            return Read(PortableUtils.ReadDecimalArray, PortableUtils.TypeArrayDecimal);
         }
 
         /** <inheritdoc /> */
         public DateTime? ReadTimestamp(string fieldName)
         {
-            return ReadField(fieldName, PortableUtils.ReadTimestamp);
+            return ReadField(fieldName, PortableUtils.ReadTimestamp, PortableUtils.TypeTimestamp);
         }
 
         /** <inheritdoc /> */
         public DateTime? ReadTimestamp()
         {
-            return Read(PortableUtils.ReadTimestamp);
+            return Read(PortableUtils.ReadTimestamp, PortableUtils.TypeTimestamp);
         }
         
         /** <inheritdoc /> */
         public DateTime?[] ReadTimestampArray(string fieldName)
         {
-            return ReadField(fieldName, PortableUtils.ReadTimestampArray);
+            return ReadField(fieldName, PortableUtils.ReadTimestampArray, PortableUtils.TypeArrayTimestamp);
         }
         
         /** <inheritdoc /> */
         public DateTime?[] ReadTimestampArray()
         {
-            return Read(PortableUtils.ReadTimestampArray);
+            return Read(PortableUtils.ReadTimestampArray, PortableUtils.TypeArrayTimestamp);
         }
         
         /** <inheritdoc /> */
         public string ReadString(string fieldName)
         {
-            return ReadField(fieldName, PortableUtils.ReadString);
+            return ReadField(fieldName, PortableUtils.ReadString, PortableUtils.TypeString);
         }
 
         /** <inheritdoc /> */
         public string ReadString()
         {
-            return Read(PortableUtils.ReadString);
+            return Read(PortableUtils.ReadString, PortableUtils.TypeString);
         }
 
         /** <inheritdoc /> */
         public string[] ReadStringArray(string fieldName)
         {
-            return ReadField(fieldName, r => PortableUtils.ReadArray<string>(r, false));
+            return ReadField(fieldName, r => PortableUtils.ReadArray<string>(r, false), PortableUtils.TypeArrayString);
         }
 
         /** <inheritdoc /> */
         public string[] ReadStringArray()
         {
-            return Read(r => PortableUtils.ReadArray<string>(r, false));
+            return Read(r => PortableUtils.ReadArray<string>(r, false), PortableUtils.TypeArrayString);
         }
 
         /** <inheritdoc /> */
         public Guid? ReadGuid(string fieldName)
         {
-            return ReadField(fieldName, PortableUtils.ReadGuid);
+            return ReadField(fieldName, PortableUtils.ReadGuid, PortableUtils.TypeGuid);
         }
 
         /** <inheritdoc /> */
         public Guid? ReadGuid()
         {
-            return Read(PortableUtils.ReadGuid);
+            return Read(PortableUtils.ReadGuid, PortableUtils.TypeGuid);
         }
 
         /** <inheritdoc /> */
         public Guid?[] ReadGuidArray(string fieldName)
         {
-            return ReadField(fieldName, r => PortableUtils.ReadArray<Guid?>(r, false));
+            return ReadField(fieldName, r => PortableUtils.ReadArray<Guid?>(r, false), PortableUtils.TypeArrayGuid);
         }
 
         /** <inheritdoc /> */
         public Guid?[] ReadGuidArray()
         {
-            return Read(r => PortableUtils.ReadArray<Guid?>(r, false));
+            return Read(r => PortableUtils.ReadArray<Guid?>(r, false), PortableUtils.TypeArrayGuid);
         }
 
         /** <inheritdoc /> */
         public T ReadEnum<T>(string fieldName)
         {
-            return ReadField(fieldName, PortableUtils.ReadEnum<T>);
+            return ReadField(fieldName, PortableUtils.ReadEnum<T>, PortableUtils.TypeEnum);
         }
 
         /** <inheritdoc /> */
         public T ReadEnum<T>()
         {
-            return Read(PortableUtils.ReadEnum<T>);
+            return Read(PortableUtils.ReadEnum<T>, PortableUtils.TypeEnum);
         }
 
         /** <inheritdoc /> */
         public T[] ReadEnumArray<T>(string fieldName)
         {
-            return ReadField(fieldName, r => PortableUtils.ReadArray<T>(r, true));
+            return ReadField(fieldName, r => PortableUtils.ReadArray<T>(r, true), PortableUtils.TypeArrayEnum);
         }
 
         /** <inheritdoc /> */
         public T[] ReadEnumArray<T>()
         {
-            return Read(r => PortableUtils.ReadArray<T>(r, true));
+            return Read(r => PortableUtils.ReadArray<T>(r, true), PortableUtils.TypeArrayEnum);
         }
 
         /** <inheritdoc /> */
@@ -441,13 +441,13 @@ namespace Apache.Ignite.Core.Impl.Portable
         /** <inheritdoc /> */
         public T[] ReadArray<T>(string fieldName)
         {
-            return ReadField(fieldName, r => PortableUtils.ReadArray<T>(r, true));
+            return ReadField(fieldName, r => PortableUtils.ReadArray<T>(r, true), PortableUtils.TypeArray);
         }
 
         /** <inheritdoc /> */
         public T[] ReadArray<T>()
         {
-            return Read(r => PortableUtils.ReadArray<T>(r, true));
+            return Read(r => PortableUtils.ReadArray<T>(r, true), PortableUtils.TypeArray);
         }
 
         /** <inheritdoc /> */
@@ -466,14 +466,14 @@ namespace Apache.Ignite.Core.Impl.Portable
         public ICollection ReadCollection(string fieldName, PortableCollectionFactory factory,
             PortableCollectionAdder adder)
         {
-            return ReadField(fieldName, r => PortableUtils.ReadCollection(r, factory, adder));
+            return ReadField(fieldName, r => PortableUtils.ReadCollection(r, factory, adder), PortableUtils.TypeCollection);
         }
 
         /** <inheritdoc /> */
         public ICollection ReadCollection(PortableCollectionFactory factory,
             PortableCollectionAdder adder)
         {
-            return Read(r => PortableUtils.ReadCollection(r, factory, adder));
+            return Read(r => PortableUtils.ReadCollection(r, factory, adder), PortableUtils.TypeCollection);
         }
 
         /** <inheritdoc /> */
@@ -491,13 +491,13 @@ namespace Apache.Ignite.Core.Impl.Portable
         /** <inheritdoc /> */
         public IDictionary ReadDictionary(string fieldName, PortableDictionaryFactory factory)
         {
-            return ReadField(fieldName, r => PortableUtils.ReadDictionary(r, factory));
+            return ReadField(fieldName, r => PortableUtils.ReadDictionary(r, factory), PortableUtils.TypeDictionary);
         }
 
         /** <inheritdoc /> */
         public IDictionary ReadDictionary(PortableDictionaryFactory factory)
         {
-            return Read(r => PortableUtils.ReadDictionary(r, factory));
+            return Read(r => PortableUtils.ReadDictionary(r, factory), PortableUtils.TypeDictionary);
         }
 
         /// <summary>
@@ -716,9 +716,18 @@ namespace Apache.Ignite.Core.Impl.Portable
                     _curStruct = oldStruct;
                     _curRaw = oldRaw;
 
+                    // Process wrappers. We could introduce a common interface, but for only 2 if-else is faster.
                     var wrappedSerializable = obj as SerializableObjectHolder;
 
-                    return wrappedSerializable != null ? (T) wrappedSerializable.Item : (T) obj;
+                    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
@@ -742,7 +751,7 @@ namespace Apache.Ignite.Core.Impl.Portable
             {
                 object hndObj;
 
-                if (_builder == null || !_builder.CachedField(hndPos, out hndObj))
+                if (_builder == null || !_builder.TryGetCachedField(hndPos, out hndObj))
                 {
                     if (_hnds == null || !_hnds.TryGetValue(hndPos, out hndObj))
                     {
@@ -861,17 +870,24 @@ namespace Apache.Ignite.Core.Impl.Portable
         /// <summary>
         /// Determines whether header at current position is HDR_NULL.
         /// </summary>
-        private bool IsNullHeader()
+        private bool IsNotNullHeader(byte expHdr)
         {
             var hdr = ReadByte();
+            
+            if (hdr == PortableUtils.HdrNull)
+                return false;
+
+            if (expHdr != hdr)
+                throw new PortableException(string.Format("Invalid header on deserialization. " +
+                                                          "Expected: {0} but was: {1}", expHdr, hdr));
 
-            return hdr != PortableUtils.HdrNull;
+            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)
+        private bool SeekField(string fieldName, byte expHdr)
         {
             if (_curRaw)
                 throw new PortableException("Cannot read named fields after raw data is read.");
@@ -881,47 +897,47 @@ namespace Apache.Ignite.Core.Impl.Portable
             if (!SeekField(fieldId))
                 return false;
 
-            return IsNullHeader();
+            return IsNotNullHeader(expHdr);
         }
 
         /// <summary>
         /// Seeks specified field and invokes provided func.
         /// </summary>
-        private T ReadField<T>(string fieldName, Func<IPortableStream, T> readFunc)
+        private T ReadField<T>(string fieldName, Func<IPortableStream, T> readFunc, byte expHdr)
         {
-            return SeekField(fieldName) ? readFunc(Stream) : default(T);
+            return SeekField(fieldName, expHdr) ? readFunc(Stream) : default(T);
         }
 
         /// <summary>
         /// Seeks specified field and invokes provided func.
         /// </summary>
-        private T ReadField<T>(string fieldName, Func<PortableReaderImpl, T> readFunc)
+        private T ReadField<T>(string fieldName, Func<PortableReaderImpl, T> readFunc, byte expHdr)
         {
-            return SeekField(fieldName) ? readFunc(this) : default(T);
+            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)
+        private T ReadField<T>(string fieldName, Func<T> readFunc, byte expHdr)
         {
-            return SeekField(fieldName) ? readFunc() : default(T);
+            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<PortableReaderImpl, T> readFunc)
+        private T Read<T>(Func<PortableReaderImpl, T> readFunc, byte expHdr)
         {
-            return IsNullHeader() ? readFunc(this) : default(T);
+            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<IPortableStream, T> readFunc)
+        private T Read<T>(Func<IPortableStream, T> readFunc, byte expHdr)
         {
-            return IsNullHeader() ? readFunc(Stream) : default(T);
+            return IsNotNullHeader(expHdr) ? readFunc(Stream) : default(T);
         }
 
         /// <summary>

http://git-wip-us.apache.org/repos/asf/ignite/blob/05e739f1/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Portable/PortableReflectiveRoutines.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Portable/PortableReflectiveRoutines.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Portable/PortableReflectiveRoutines.cs
index d79cc0b..4aff797 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Portable/PortableReflectiveRoutines.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Portable/PortableReflectiveRoutines.cs
@@ -254,11 +254,6 @@ namespace Apache.Ignite.Core.Impl.Portable
                 writeAction = GetWriter<Guid?[]>(field, (f, w, o) => w.WriteGuidArray(f, o));
                 readAction = GetReader(field, (f, r) => r.ReadGuidArray(f));
             } 
-            else if (elemType == typeof(DateTime?))
-            {
-                writeAction = GetWriter<DateTime?[]>(field, (f, w, o) => w.WriteTimestampArray(f, o));
-                readAction = GetReader(field, (f, r) => r.ReadTimestampArray(f));
-            }
             else if (elemType.IsEnum)
             {
                 writeAction = GetWriter(field, MthdWriteEnumArray, elemType);
@@ -308,16 +303,6 @@ namespace Apache.Ignite.Core.Impl.Portable
                 writeAction = GetWriter<Guid?>(field, (f, w, o) => w.WriteGuid(f, o));
                 readAction = GetReader(field, (f, r) => r.ReadGuid(f));
             } 
-            else if (type == typeof(DateTime))
-            {
-                writeAction = GetWriter<DateTime>(field, (f, w, o) => w.WriteTimestamp(f, o));
-                readAction = GetReader(field, (f, r) => r.ReadTimestamp(f));
-            }
-            else if (nullable && nullableType == typeof(DateTime))
-            {
-                writeAction = GetWriter<DateTime?>(field, (f, w, o) => w.WriteTimestamp(f, o));
-                readAction = GetReader(field, (f, r) => r.ReadTimestamp(f));
-            }
             else if (type.IsEnum)
             {
                 writeAction = GetWriter<object>(field, (f, w, o) => w.WriteEnum(f, o), true);

http://git-wip-us.apache.org/repos/asf/ignite/blob/05e739f1/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Portable/PortableSystemHandlers.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Portable/PortableSystemHandlers.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Portable/PortableSystemHandlers.cs
index ed2e9ea..dabe5c8 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Portable/PortableSystemHandlers.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Portable/PortableSystemHandlers.cs
@@ -42,10 +42,50 @@ namespace Apache.Ignite.Core.Impl.Portable
             new Dictionary<Type, PortableSystemWriteDelegate>();
 
         /** Mutex for write handlers update. */
-        private static readonly Object WriteHandlersMux = new Object();
+        private static readonly object WriteHandlersMux = new object();
 
         /** Read handlers. */
         private static readonly IPortableSystemReader[] ReadHandlers = new IPortableSystemReader[255];
+
+        /** Type ids. */
+        private static readonly Dictionary<Type, byte> TypeIds = new Dictionary<Type, byte>
+        {
+            {typeof (bool), PortableUtils.TypeBool},
+            {typeof (byte), PortableUtils.TypeByte},
+            {typeof (sbyte), PortableUtils.TypeByte},
+            {typeof (short), PortableUtils.TypeShort},
+            {typeof (ushort), PortableUtils.TypeShort},
+            {typeof (char), PortableUtils.TypeChar},
+            {typeof (int), PortableUtils.TypeInt},
+            {typeof (uint), PortableUtils.TypeInt},
+            {typeof (long), PortableUtils.TypeLong},
+            {typeof (ulong), PortableUtils.TypeLong},
+            {typeof (float), PortableUtils.TypeFloat},
+            {typeof (double), PortableUtils.TypeDouble},
+            {typeof (string), PortableUtils.TypeString},
+            {typeof (decimal), PortableUtils.TypeDecimal},
+            {typeof (Guid), PortableUtils.TypeGuid},
+            {typeof (Guid?), PortableUtils.TypeGuid},
+            {typeof (ArrayList), PortableUtils.TypeCollection},
+            {typeof (Hashtable), PortableUtils.TypeDictionary},
+            {typeof (DictionaryEntry), PortableUtils.TypeMapEntry},
+            {typeof (bool[]), PortableUtils.TypeArrayBool},
+            {typeof (byte[]), PortableUtils.TypeArrayByte},
+            {typeof (sbyte[]), PortableUtils.TypeArrayByte},
+            {typeof (short[]), PortableUtils.TypeArrayShort},
+            {typeof (ushort[]), PortableUtils.TypeArrayShort},
+            {typeof (char[]), PortableUtils.TypeArrayChar},
+            {typeof (int[]), PortableUtils.TypeArrayInt},
+            {typeof (uint[]), PortableUtils.TypeArrayInt},
+            {typeof (long[]), PortableUtils.TypeArrayLong},
+            {typeof (ulong[]), PortableUtils.TypeArrayLong},
+            {typeof (float[]), PortableUtils.TypeArrayFloat},
+            {typeof (double[]), PortableUtils.TypeArrayDouble},
+            {typeof (string[]), PortableUtils.TypeArrayString},
+            {typeof (decimal?[]), PortableUtils.TypeArrayDecimal},
+            {typeof (Guid?[]), PortableUtils.TypeArrayGuid},
+            {typeof (object[]), PortableUtils.TypeArray}
+        };
         
         /// <summary>
         /// Initializes the <see cref="PortableSystemHandlers"/> class.
@@ -214,8 +254,6 @@ namespace Apache.Ignite.Core.Impl.Portable
                     return WriteDecimalArray;
                 if (elemType == typeof(string))
                     return WriteStringArray;
-                if (elemType == typeof(DateTime?))
-                    return WriteTimestampArray;
                 if (elemType == typeof(Guid?))
                     return WriteGuidArray;
                 // Enums.
@@ -231,10 +269,34 @@ namespace Apache.Ignite.Core.Impl.Portable
                 // We know how to write enums.
                 return WriteEnum;
 
+            if (type.IsSerializable)
+                return WriteSerializable;
+
             return null;
         }
 
         /// <summary>
+        /// Find write handler for type.
+        /// </summary>
+        /// <param name="type">Type.</param>
+        /// <returns>Write handler or NULL.</returns>
+        public static byte GetTypeId(Type type)
+        {
+            byte res;
+
+            if (TypeIds.TryGetValue(type, out res))
+                return res;
+
+            if (type.IsEnum)
+                return PortableUtils.TypeEnum;
+
+            if (type.IsArray && type.GetElementType().IsEnum)
+                return PortableUtils.TypeArrayEnum;
+
+            return PortableUtils.TypeObject;
+        }
+
+        /// <summary>
         /// Add write handler for type.
         /// </summary>
         /// <param name="type"></param>
@@ -295,9 +357,7 @@ namespace Apache.Ignite.Core.Impl.Portable
         /// <param name="obj">Value.</param>
         private static void WriteDate(PortableWriterImpl ctx, object obj)
         {
-            ctx.Stream.WriteByte(PortableUtils.TypeTimestamp);
-
-            PortableUtils.WriteTimestamp((DateTime)obj, ctx.Stream);
+            ctx.Write(new DateTimeHolder((DateTime) obj));
         }
         
         /// <summary>
@@ -481,18 +541,6 @@ namespace Apache.Ignite.Core.Impl.Portable
         }
         
         /// <summary>
-        /// Write nullable date array.
-        /// </summary>
-        /// <param name="ctx">Context.</param>
-        /// <param name="obj">Value.</param>
-        private static void WriteTimestampArray(PortableWriterImpl ctx, object obj)
-        {
-            ctx.Stream.WriteByte(PortableUtils.TypeArrayTimestamp);
-
-            PortableUtils.WriteTimestampArray((DateTime?[])obj, ctx.Stream);
-        }
-
-        /// <summary>
         /// Write string array.
         /// </summary>
         /// <param name="ctx">Context.</param>
@@ -586,6 +634,16 @@ namespace Apache.Ignite.Core.Impl.Portable
             PortableUtils.WriteEnum(ctx.Stream, (Enum)obj);
         }
 
+        /// <summary>
+        /// Writes serializable.
+        /// </summary>
+        /// <param name="writer">The writer.</param>
+        /// <param name="o">The object.</param>
+        private static void WriteSerializable(PortableWriterImpl writer, object o)
+        {
+            writer.Write(new SerializableObjectHolder(o));
+        }
+
         /**
          * <summary>Read enum array.</summary>
          */

http://git-wip-us.apache.org/repos/asf/ignite/blob/05e739f1/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Portable/PortableUserObject.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Portable/PortableUserObject.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Portable/PortableUserObject.cs
index 9df180d..c241b96 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Portable/PortableUserObject.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Portable/PortableUserObject.cs
@@ -80,7 +80,24 @@ namespace Apache.Ignite.Core.Impl.Portable
         /** <inheritdoc /> */
         public T GetField<T>(string fieldName)
         {
-            return Field<T>(fieldName, null);
+            int pos;
+
+            return TryGetFieldPosition(fieldName, out pos) ? GetField<T>(pos, null) : default(T);
+        }
+
+        /// <summary>
+        /// Gets field value on the given object.
+        /// </summary>
+        /// <param name="pos">Position.</param>
+        /// <param name="builder">Builder.</param>
+        /// <returns>Field value.</returns>
+        public T GetField<T>(int pos, PortableBuilderImpl builder)
+        {
+            IPortableStream stream = new PortableHeapStream(_data);
+
+            stream.Seek(pos, SeekOrigin.Begin);
+
+            return _marsh.Unmarshal<T>(stream, PortableMode.ForcePortable, builder);
         }
 
         /** <inheritdoc /> */
@@ -139,42 +156,15 @@ namespace Apache.Ignite.Core.Impl.Portable
             get { return _offset; }
         }
 
-        /// <summary>
-        /// Get field with builder.
-        /// </summary>
-        /// <typeparam name="T"></typeparam>
-        /// <param name="fieldName"></param>
-        /// <param name="builder"></param>
-        /// <returns></returns>
-        public T Field<T>(string fieldName, PortableBuilderImpl builder)
+        public bool TryGetFieldPosition(string fieldName, out int pos)
         {
-            IPortableTypeDescriptor desc = _marsh.GetDescriptor(true, _typeId);
+            var desc = _marsh.GetDescriptor(true, _typeId);
 
             InitializeFields();
 
             int fieldId = PortableUtils.FieldId(_typeId, fieldName, desc.NameConverter, desc.Mapper);
 
-            int pos;
-
-            if (_fields.TryGetValue(fieldId, out pos))
-            {
-                if (builder != null)
-                {
-                    // Read in scope of build process.
-                    T res;
-
-                    if (!builder.CachedField(pos, out res))
-                    {
-                        res = Field0<T>(pos, builder);
-
-                        builder.CacheField(pos, res);
-                    }
-
-                    return res;
-                }
-                return Field0<T>(pos, null);
-            }
-            return default(T);
+            return _fields.TryGetValue(fieldId, out pos);
         }
 
         /// <summary>
@@ -194,21 +184,6 @@ namespace Apache.Ignite.Core.Impl.Portable
             }
         }
 
-        /// <summary>
-        /// Gets field value on the given object.
-        /// </summary>
-        /// <param name="pos">Position.</param>
-        /// <param name="builder">Builder.</param>
-        /// <returns>Field value.</returns>
-        private T Field0<T>(int pos, PortableBuilderImpl builder)
-        {
-            IPortableStream stream = new PortableHeapStream(_data);
-
-            stream.Seek(pos, SeekOrigin.Begin);
-
-            return _marsh.Unmarshal<T>(stream, PortableMode.ForcePortable, builder);
-        }
-
         /** <inheritdoc /> */
         public override int GetHashCode()
         {
@@ -247,8 +222,8 @@ namespace Apache.Ignite.Core.Impl.Portable
                     // 3. Check if objects have the same field values.
                     foreach (KeyValuePair<int, int> field in _fields)
                     {
-                        object fieldVal = Field0<object>(field.Value, null);
-                        object thatFieldVal = that.Field0<object>(that._fields[field.Key], null);
+                        object fieldVal = GetField<object>(field.Value, null);
+                        object thatFieldVal = that.GetField<object>(that._fields[field.Key], null);
 
                         if (!Equals(fieldVal, thatFieldVal))
                             return false;
@@ -332,7 +307,7 @@ namespace Apache.Ignite.Core.Impl.Portable
                         {
                             sb.Append(fieldName).Append('=');
 
-                            ToString0(sb, Field0<object>(fieldPos, null), handled);
+                            ToString0(sb, GetField<object>(fieldPos, null), handled);
                         }
                     }
                 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/05e739f1/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Portable/PortableUtils.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Portable/PortableUtils.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Portable/PortableUtils.cs
index dd72a8c..c9d6172 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Portable/PortableUtils.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Portable/PortableUtils.cs
@@ -26,8 +26,6 @@ namespace Apache.Ignite.Core.Impl.Portable
     using System.IO;
     using System.Reflection;
     using System.Runtime.InteropServices;
-    using System.Runtime.Serialization.Formatters.Binary;
-    using System.Security.Policy;
     using System.Text;
 
     using Apache.Ignite.Core.Impl.Common;
@@ -189,9 +187,12 @@ namespace Apache.Ignite.Core.Impl.Portable
         /** Type: Compute job wrapper. */
         public const byte TypeComputeJobWrapper = 86;
 
-        /** Type: Compute job wrapper. */
+        /** Type: Serializable wrapper. */
         public const byte TypeSerializableHolder = 87;
 
+        /** Type: DateTime wrapper. */
+        public const byte TypeDateTimeHolder = 93;
+
         /** Type: action wrapper. */
         public const byte TypeComputeActionJob = 88;
 
@@ -204,15 +205,9 @@ namespace Apache.Ignite.Core.Impl.Portable
         /** Type: message filter holder. */
         public const byte TypeMessageListenerHolder = 92;
 
-        /** Type: message filter holder. */
-        public const byte TypePortableOrSerializableHolder = 93;
-
         /** Type: stream receiver holder. */
         public const byte TypeStreamReceiverHolder = 94;
 
-        /** Type: DateTime. */
-        public const byte TypeDateTime = 95;
-
         /** Collection: custom. */
         public const byte CollectionCustom = 0;
 
@@ -1753,7 +1748,11 @@ namespace Apache.Ignite.Core.Impl.Portable
          */
         private static void ToJavaDate(DateTime date, out long high, out int low)
         {
-            long diff = date.ToUniversalTime().Ticks - JavaDateTicks;
+            if (date.Kind != DateTimeKind.Utc)
+                throw new InvalidOperationException(
+                    "DateTime is not UTC. Only UTC DateTime can be used for interop with other platforms.");
+
+            long diff = date.Ticks - JavaDateTicks;
 
             high = diff / TimeSpan.TicksPerMillisecond;
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/05e739f1/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Portable/PortableWriterImpl.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Portable/PortableWriterImpl.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Portable/PortableWriterImpl.cs
index d5fb6ec..ab7adaa 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Portable/PortableWriterImpl.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Portable/PortableWriterImpl.cs
@@ -951,6 +951,15 @@ namespace Apache.Ignite.Core.Impl.Portable
         /// <param name="val">Object array.</param>
         public void WriteArray<T>(T[] val)
         {
+            WriteArrayInternal(val);
+        }
+
+        /// <summary>
+        /// Write object array.
+        /// </summary>
+        /// <param name="val">Object array.</param>
+        public void WriteArrayInternal(Array val)
+        {
             if (val == null)
                 WriteNullRawField();
             else
@@ -1025,7 +1034,7 @@ namespace Apache.Ignite.Core.Impl.Portable
         /// <summary>
         /// Write NULL field.
         /// </summary>
-        public void WriteNullField()
+        private void WriteNullField()
         {
             _stream.WriteInt(1);
             _stream.WriteByte(PU.HdrNull);
@@ -1034,7 +1043,7 @@ namespace Apache.Ignite.Core.Impl.Portable
         /// <summary>
         /// Write NULL raw field.
         /// </summary>
-        public void WriteNullRawField()
+        private void WriteNullRawField()
         {
             _stream.WriteByte(PU.HdrNull);
         }
@@ -1173,18 +1182,12 @@ namespace Apache.Ignite.Core.Impl.Portable
             else
             {
                 // Are we dealing with a well-known type?
-                PortableSystemWriteDelegate handler = PortableSystemHandlers.GetWriteHandler(type);
+                var handler = PortableSystemHandlers.GetWriteHandler(type);
 
-                if (handler != null)
-                    handler.Invoke(this, obj);
-                else
-                {
-                    if (type.IsSerializable)
-                        Write(new SerializableObjectHolder(obj));
-                    else
-                    // We did our best, object cannot be marshalled.
-                        throw new PortableException("Unsupported object type [type=" + type + ", object=" + obj + ']');
-                }
+                if (handler == null)  // We did our best, object cannot be marshalled.
+                    throw new PortableException("Unsupported object type [type=" + type + ", object=" + obj + ']');
+                
+                handler(this, obj);
             }
         }
 
@@ -1193,7 +1196,7 @@ namespace Apache.Ignite.Core.Impl.Portable
         /// </summary>
         /// <param name="val">Object.</param>
         /// <param name="type">Type.</param>
-        public unsafe void WritePrimitive<T>(T val, Type type)
+        private unsafe void WritePrimitive<T>(T val, Type type)
         {
             // .Net defines 14 primitive types. We support 12 - excluding IntPtr and UIntPtr.
             // Types check sequence is designed to minimize comparisons for the most frequent types.


Mime
View raw message