http://git-wip-us.apache.org/repos/asf/ignite/blob/ec58b87c/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Portable/PortableWriterImpl.cs
----------------------------------------------------------------------
diff --cc 
modules/platforms/dotnet/Apache.Ignite.Core/Impl/Portable/PortableWriterImpl.cs
index 0000000,b490460..6146362
mode 000000,100644..100644
--- 
a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Portable/PortableWriterImpl.cs
+++ 
b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Portable/PortableWriterImpl.cs
@@@ -1,0 -1,1619 +1,1620 @@@
+ /*
+  * 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.Collections;
+     using System.Collections.Generic;
+     using System.IO;
+ 
+     using Apache.Ignite.Core.Impl.Portable.IO;
+     using Apache.Ignite.Core.Impl.Portable.Metadata;
+     using Apache.Ignite.Core.Impl.Portable.Structure;
+     using Apache.Ignite.Core.Portable;
+ 
+     using PU = PortableUtils;
+ 
+     /// <summary>
+     /// Portable writer implementation.
+     /// </summary>
+     internal class PortableWriterImpl : IPortableWriter, IPortableRawWriter
+     {
+         /** Marshaller. */
+         private readonly PortableMarshaller _marsh;
+ 
+         /** Stream. */
+         private readonly IPortableStream _stream;
+ 
+         /** Builder (used only during build). */
+         private PortableBuilderImpl _builder;
+ 
+         /** Handles. */
+         private PortableHandleDictionary<object, long> _hnds;
+ 
+         /** Metadatas collected during this write session. */
+         private IDictionary<int, IPortableMetadata> _metas;
+ 
+         /** Current type ID. */
+         private int _curTypeId;
+ 
+         /** Current name converter */
+         private IPortableNameMapper _curConverter;
+ 
+         /** Current mapper. */
+         private IPortableIdMapper _curMapper;
+         
+         /** Current raw position. */
+         private long _curRawPos;
+ 
+         /** Current type structure. */
+         private PortableStructure _curStruct;
+ 
+         /** Current type structure path index. */
+         private int _curStructPath;
+ 
+         /** Current type structure action index. */
+         private int _curStructAction;
+ 
+         /** Current type structure updates. */
+         private List<PortableStructureUpdate> _curStructUpdates; 
+         
+         /** Whether we are currently detaching an object. */
+         private bool _detaching;
+ 
+         /// <summary>
+         /// Gets the marshaller.
+         /// </summary>
+         internal PortableMarshaller Marshaller
+         {
+             get { return _marsh; }
+         }
+ 
+         /// <summary>
+         /// Write named boolean value.
+         /// </summary>
+         /// <param name="fieldName">Field name.</param>
+         /// <param name="val">Boolean value.</param>
+         public void WriteBoolean(string fieldName, bool val)
+         {
+             WriteFieldId(fieldName, PU.TypeBool);
+ 
+             _stream.WriteInt(PU.LengthTypeId + 1);
+             _stream.WriteByte(PU.TypeBool);
+             _stream.WriteBool(val);
+         }
+         
+         /// <summary>
+         /// Write boolean value.
+         /// </summary>
+         /// <param name="val">Boolean value.</param>
+         public void WriteBoolean(bool val)
+         {
+             _stream.WriteBool(val);
+         }
+ 
+         /// <summary>
+         /// Write named boolean array.
+         /// </summary>
+         /// <param name="fieldName">Field name.</param>
+         /// <param name="val">Boolean array.</param>
+         public void WriteBooleanArray(string fieldName, bool[] val)
+         {
+             WriteFieldId(fieldName, PU.TypeArrayBool);
+ 
+             if (val == null)
+                 WriteNullField();
+             else
+             {
+                 _stream.WriteInt(PU.LengthTypeId + PU.LengthArraySize + 
val.Length);
+                 _stream.WriteByte(PU.TypeArrayBool);
+                 PU.WriteBooleanArray(val, _stream);
+             }
+         }
+ 
+         /// <summary>
+         /// Write boolean array.
+         /// </summary>
+         /// <param name="val">Boolean array.</param>
+         public void WriteBooleanArray(bool[] val)
+         {
+             if (val == null)
+                 WriteNullRawField();
+             else
+             {
+                 _stream.WriteByte(PU.TypeArrayBool);
+                 PU.WriteBooleanArray(val, _stream);
+             }
+         }
+ 
+         /// <summary>
+         /// Write named byte value.
+         /// </summary>
+         /// <param name="fieldName">Field name.</param>
+         /// <param name="val">Byte value.</param>
+         public void WriteByte(string fieldName, byte val)
+         {
+             WriteFieldId(fieldName, PU.TypeBool);
+ 
+             _stream.WriteInt(PU.LengthTypeId + 1);
+             _stream.WriteByte(PU.TypeByte);
+             _stream.WriteByte(val);
+         }
+ 
+         /// <summary>
+         /// Write byte value.
+         /// </summary>
+         /// <param name="val">Byte value.</param>
+         public void WriteByte(byte val)
+         {
+             _stream.WriteByte(val);
+         }
+ 
+         /// <summary>
+         /// Write named byte array.
+         /// </summary>
+         /// <param name="fieldName">Field name.</param>
+         /// <param name="val">Byte array.</param>
+         public void WriteByteArray(string fieldName, byte[] val)
+         {
+             WriteFieldId(fieldName, PU.TypeArrayByte);
+ 
+             if (val == null)
+                 WriteNullField();
+             else
+             {
+                 _stream.WriteInt(PU.LengthTypeId + PU.LengthArraySize + 
val.Length);
+                 _stream.WriteByte(PU.TypeArrayByte);
+                 PU.WriteByteArray(val, _stream);
+             }
+         }
+ 
+         /// <summary>
+         /// Write byte array.
+         /// </summary>
+         /// <param name="val">Byte array.</param>
+         public void WriteByteArray(byte[] val)
+         {
+             if (val == null)
+                 WriteNullRawField();
+             else
+             {
+                 _stream.WriteByte(PU.TypeArrayByte);
+                 PU.WriteByteArray(val, _stream);
+             }
+         }
+ 
+         /// <summary>
+         /// Write named short value.
+         /// </summary>
+         /// <param name="fieldName">Field name.</param>
+         /// <param name="val">Short value.</param>
+         public void WriteShort(string fieldName, short val)
+         {
+             WriteFieldId(fieldName, PU.TypeShort);
+ 
+             _stream.WriteInt(PU.LengthTypeId + 2);
+             _stream.WriteByte(PU.TypeShort);
+             _stream.WriteShort(val);
+         }
+ 
+         /// <summary>
+         /// Write short value.
+         /// </summary>
+         /// <param name="val">Short value.</param>
+         public void WriteShort(short val)
+         {
+             _stream.WriteShort(val);
+         }
+ 
+         /// <summary>
+         /// Write named short array.
+         /// </summary>
+         /// <param name="fieldName">Field name.</param>
+         /// <param name="val">Short array.</param>
+         public void WriteShortArray(string fieldName, short[] val)
+         {
+             WriteFieldId(fieldName, PU.TypeArrayShort);
+ 
+             if (val == null)
+                 WriteNullField();
+             else
+             {
+                 _stream.WriteInt(PU.LengthTypeId + PU.LengthArraySize + 
(val.Length << 1));
+                 _stream.WriteByte(PU.TypeArrayShort);
+                 PU.WriteShortArray(val, _stream);
+             }
+         }
+ 
+         /// <summary>
+         /// Write short array.
+         /// </summary>
+         /// <param name="val">Short array.</param>
+         public void WriteShortArray(short[] val)
+         {
+             if (val == null)
+                 WriteNullRawField();
+             else
+             {
+                 _stream.WriteByte(PU.TypeArrayShort);
+                 PU.WriteShortArray(val, _stream);
+             }
+         }
+ 
+         /// <summary>
+         /// Write named char value.
+         /// </summary>
+         /// <param name="fieldName">Field name.</param>
+         /// <param name="val">Char value.</param>
+         public void WriteChar(string fieldName, char val)
+         {
+             WriteFieldId(fieldName, PU.TypeChar);
+ 
+             _stream.WriteInt(PU.LengthTypeId + 2);
+             _stream.WriteByte(PU.TypeChar);
+             _stream.WriteChar(val);
+         }
+ 
+         /// <summary>
+         /// Write char value.
+         /// </summary>
+         /// <param name="val">Char value.</param>
+         public void WriteChar(char val)
+         {
+             _stream.WriteChar(val);
+         }
+ 
+         /// <summary>
+         /// Write named char array.
+         /// </summary>
+         /// <param name="fieldName">Field name.</param>
+         /// <param name="val">Char array.</param>
+         public void WriteCharArray(string fieldName, char[] val)
+         {
+             WriteFieldId(fieldName, PU.TypeArrayChar);
+ 
+             if (val == null)
+                 WriteNullField();
+             else
+             {
+                 _stream.WriteInt(PU.LengthTypeId + PU.LengthArraySize + 
(val.Length << 1));
+                 _stream.WriteByte(PU.TypeArrayChar);
+                 PU.WriteCharArray(val, _stream);
+             }
+         }
+ 
+         /// <summary>
+         /// Write char array.
+         /// </summary>
+         /// <param name="val">Char array.</param>
+         public void WriteCharArray(char[] val)
+         {
+             if (val == null)
+                 WriteNullRawField();
+             else
+             {
+                 _stream.WriteByte(PU.TypeArrayChar);
+                 PU.WriteCharArray(val, _stream);
+             }
+         }
+ 
+         /// <summary>
+         /// Write named int value.
+         /// </summary>
+         /// <param name="fieldName">Field name.</param>
+         /// <param name="val">Int value.</param>
+         public void WriteInt(string fieldName, int val)
+         {
+             WriteFieldId(fieldName, PU.TypeInt);
+ 
+             _stream.WriteInt(PU.LengthTypeId + 4);
+             _stream.WriteByte(PU.TypeInt);
+             _stream.WriteInt(val);
+         }
+ 
+         /// <summary>
+         /// Write int value.
+         /// </summary>
+         /// <param name="val">Int value.</param>
+         public void WriteInt(int val)
+         {
+             _stream.WriteInt(val);
+         }
+ 
+         /// <summary>
+         /// Write named int array.
+         /// </summary>
+         /// <param name="fieldName">Field name.</param>
+         /// <param name="val">Int array.</param>
+         public void WriteIntArray(string fieldName, int[] val)
+         {
+             WriteFieldId(fieldName, PU.TypeArrayInt);
+ 
+             if (val == null)
+                 WriteNullField();
+             else
+             {
+                 _stream.WriteInt(PU.LengthTypeId + PU.LengthArraySize + 
(val.Length << 2));
+                 _stream.WriteByte(PU.TypeArrayInt);
+                 PU.WriteIntArray(val, _stream);
+             }
+         }
+ 
+         /// <summary>
+         /// Write int array.
+         /// </summary>
+         /// <param name="val">Int array.</param>
+         public void WriteIntArray(int[] val)
+         {
+             if (val == null)
+                 WriteNullRawField();
+             else
+             {
+                 _stream.WriteByte(PU.TypeArrayInt);
+                 PU.WriteIntArray(val, _stream);
+             }
+         }
+ 
+         /// <summary>
+         /// Write named long value.
+         /// </summary>
+         /// <param name="fieldName">Field name.</param>
+         /// <param name="val">Long value.</param>
+         public void WriteLong(string fieldName, long val)
+         {
+             WriteFieldId(fieldName, PU.TypeLong);
+ 
+             _stream.WriteInt(PU.LengthTypeId + 8);
+             _stream.WriteByte(PU.TypeLong);
+             _stream.WriteLong(val);
+         }
+ 
+         /// <summary>
+         /// Write long value.
+         /// </summary>
+         /// <param name="val">Long value.</param>
+         public void WriteLong(long val)
+         {
+             _stream.WriteLong(val);
+         }
+ 
+         /// <summary>
+         /// Write named long array.
+         /// </summary>
+         /// <param name="fieldName">Field name.</param>
+         /// <param name="val">Long array.</param>
+         public void WriteLongArray(string fieldName, long[] val)
+         {
+             WriteFieldId(fieldName, PU.TypeArrayLong);
+ 
+             if (val == null)
+                 WriteNullField();
+             else
+             {
+                 _stream.WriteInt(PU.LengthTypeId + PU.LengthArraySize + 
(val.Length << 3));
+                 _stream.WriteByte(PU.TypeArrayLong);
+                 PU.WriteLongArray(val, _stream);
+             }
+         }
+ 
+         /// <summary>
+         /// Write long array.
+         /// </summary>
+         /// <param name="val">Long array.</param>
+         public void WriteLongArray(long[] val)
+         {
+             if (val == null)
+                 WriteNullRawField();
+             else
+             {
+                 _stream.WriteByte(PU.TypeArrayLong);
+                 PU.WriteLongArray(val, _stream);
+             }
+         }
+ 
+         /// <summary>
+         /// Write named float value.
+         /// </summary>
+         /// <param name="fieldName">Field name.</param>
+         /// <param name="val">Float value.</param>
+         public void WriteFloat(string fieldName, float val)
+         {
+             WriteFieldId(fieldName, PU.TypeFloat);
+ 
+             _stream.WriteInt(PU.LengthTypeId + 4);
+             _stream.WriteByte(PU.TypeFloat);
+             _stream.WriteFloat(val);
+         }
+ 
+         /// <summary>
+         /// Write float value.
+         /// </summary>
+         /// <param name="val">Float value.</param>
+         public void WriteFloat(float val)
+         {
+             _stream.WriteFloat(val);
+         }
+ 
+         /// <summary>
+         /// Write named float array.
+         /// </summary>
+         /// <param name="fieldName">Field name.</param>
+         /// <param name="val">Float array.</param>
+         public void WriteFloatArray(string fieldName, float[] val)
+         {
+             WriteFieldId(fieldName, PU.TypeArrayFloat);
+ 
+             if (val == null)
+                 WriteNullField();
+             else
+             {
+                 _stream.WriteInt(PU.LengthTypeId + PU.LengthArraySize + 
(val.Length << 2));
+                 _stream.WriteByte(PU.TypeArrayFloat);
+                 PU.WriteFloatArray(val, _stream);
+             }
+         }
+ 
+         /// <summary>
+         /// Write float array.
+         /// </summary>
+         /// <param name="val">Float array.</param>
+         public void WriteFloatArray(float[] val)
+         {
+             if (val == null)
+                 WriteNullRawField();
+             else
+             {
+                 _stream.WriteByte(PU.TypeArrayFloat);
+                 PU.WriteFloatArray(val, _stream);
+             }
+         }
+ 
+         /// <summary>
+         /// Write named double value.
+         /// </summary>
+         /// <param name="fieldName">Field name.</param>
+         /// <param name="val">Double value.</param>
+         public void WriteDouble(string fieldName, double val)
+         {
+             WriteFieldId(fieldName, PU.TypeDouble);
+ 
+             _stream.WriteInt(PU.LengthTypeId + 8);
+             _stream.WriteByte(PU.TypeDouble);
+             _stream.WriteDouble(val);
+         }
+ 
+         /// <summary>
+         /// Write double value.
+         /// </summary>
+         /// <param name="val">Double value.</param>
+         public void WriteDouble(double val)
+         {
+             _stream.WriteDouble(val);
+         }
+ 
+         /// <summary>
+         /// Write named double array.
+         /// </summary>
+         /// <param name="fieldName">Field name.</param>
+         /// <param name="val">Double array.</param>
+         public void WriteDoubleArray(string fieldName, double[] val)
+         {
+             WriteFieldId(fieldName, PU.TypeArrayDouble);
+ 
+             if (val == null)
+                 WriteNullField();
+             else
+             {
+                 _stream.WriteInt(PU.LengthTypeId + PU.LengthArraySize + 
(val.Length << 3));
+                 _stream.WriteByte(PU.TypeArrayDouble);
+                 PU.WriteDoubleArray(val, _stream);
+             }
+         }
+ 
+         /// <summary>
+         /// Write double array.
+         /// </summary>
+         /// <param name="val">Double array.</param>
+         public void WriteDoubleArray(double[] val)
+         {
+             if (val == null)
+                 WriteNullRawField();
+             else
+             {
+                 _stream.WriteByte(PU.TypeArrayDouble);
+                 PU.WriteDoubleArray(val, _stream);
+             }
+         }
+ 
+         /// <summary>
+         /// Write named decimal value.
+         /// </summary>
+         /// <param name="fieldName">Field name.</param>
+         /// <param name="val">Decimal value.</param>
+         public void WriteDecimal(string fieldName, decimal? val)
+         {
+             WriteFieldId(fieldName, PU.TypeDecimal);
+ 
+             if (val == null)
+                 WriteNullField();
+             else
+             {
+                 int pos = SkipFieldLength();
+ 
+                 _stream.WriteByte(PU.TypeDecimal);
+                 PortableUtils.WriteDecimal(val.Value, _stream);
+ 
+                 WriteFieldLength(_stream, pos);
+             }
+         }
+ 
+         /// <summary>
+         /// Write decimal value.
+         /// </summary>
+         /// <param name="val">Decimal value.</param>
+         public void WriteDecimal(decimal? val)
+         {
+             if (val == null)
+                 WriteNullRawField();
+             else
+             {
+                 _stream.WriteByte(PU.TypeDecimal);
+                 PortableUtils.WriteDecimal(val.Value, _stream);
+             }
+         }
+ 
+         /// <summary>
+         /// Write named decimal array.
+         /// </summary>
+         /// <param name="fieldName">Field name.</param>
+         /// <param name="val">Decimal array.</param>
+         public void WriteDecimalArray(string fieldName, decimal?[] val)
+         {
+             WriteFieldId(fieldName, PU.TypeArrayDecimal);
+ 
+             if (val == null)
+                 WriteNullField();
+             else
+             {
+                 int pos = SkipFieldLength();
+ 
+                 _stream.WriteByte(PU.TypeArrayDecimal);
+                 PU.WriteDecimalArray(val, _stream);
+ 
+                 WriteFieldLength(_stream, pos);
+             }
+         }
+         
+         /// <summary>
+         /// Write decimal array.
+         /// </summary>
+         /// <param name="val">Decimal array.</param>
+         public void WriteDecimalArray(decimal?[] val)
+         {
+             if (val == null)
+                 WriteNullRawField();
+             else
+             {
+                 _stream.WriteByte(PU.TypeArrayDecimal);
+                 PU.WriteDecimalArray(val, _stream);
+             }
+         }
+ 
+         /// <summary>
+         /// Write named date value.
+         /// </summary>
+         /// <param name="fieldName">Field name.</param>
+         /// <param name="val">Date value.</param>
+         public void WriteDate(string fieldName, DateTime? val)
+         {
+             WriteFieldId(fieldName, PU.TypeDate);
+ 
+             if (val == null)
+                 WriteNullField();
+             else
+             {
+                 _stream.WriteInt(PU.LengthTypeId + 12);
+ 
+                 _stream.WriteByte(PortableUtils.TypeDate);
+                 PortableUtils.WriteDate(val.Value, _stream);
+             }
+         }
+         
+         /// <summary>
+         /// Write date value.
+         /// </summary>
+         /// <param name="val">Date value.</param>
+         public void WriteDate(DateTime? val)
+         {
+             if (val == null)
+                 WriteNullRawField();
+             else
+             {
+                 _stream.WriteByte(PortableUtils.TypeDate);
+                 PortableUtils.WriteDate(val.Value, _stream);
+             }
+         }
+ 
+         /// <summary>
+         /// Write named date array.
+         /// </summary>
+         /// <param name="fieldName">Field name.</param>
+         /// <param name="val">Date array.</param>
+         public void WriteDateArray(string fieldName, DateTime?[] val)
+         {
+             WriteFieldId(fieldName, PU.TypeDate);
+ 
+             if (val == null)
+                 WriteNullField();
+             else
+             {
+                 int pos = SkipFieldLength();
+ 
+                 _stream.WriteByte(PortableUtils.TypeArrayDate);
+                 PortableUtils.WriteDateArray(val, _stream);
+ 
+                 WriteFieldLength(_stream, pos);
+             }
+         }
+ 
+         /// <summary>
+         /// Write date array.
+         /// </summary>
+         /// <param name="val">Date array.</param>
+         public void WriteDateArray(DateTime?[] val)
+         {
+             if (val == null)
+                 WriteNullRawField();
+             else
+             {
+                 _stream.WriteByte(PortableUtils.TypeArrayDate);
+                 PortableUtils.WriteDateArray(val, _stream);
+             }
+         }
+ 
+         /// <summary>
+         /// Write named string value.
+         /// </summary>
+         /// <param name="fieldName">Field name.</param>
+         /// <param name="val">String value.</param>
+         public void WriteString(string fieldName, string val)
+         {
+             WriteFieldId(fieldName, PU.TypeString);
+ 
+             if (val == null)
+                 WriteNullField();
+             else
+             {
+                 int pos = SkipFieldLength();
+ 
+                 _stream.WriteByte(PU.TypeString);
+                 PU.WriteString(val, _stream);
+ 
+                 WriteFieldLength(_stream, pos);
+             }
+         }
+ 
+         /// <summary>
+         /// Write string value.
+         /// </summary>
+         /// <param name="val">String value.</param>
+         public void WriteString(string val)
+         {
+             if (val == null)
+                 WriteNullRawField();
+             else
+             {
+                 _stream.WriteByte(PU.TypeString);
+                 PU.WriteString(val, _stream);
+             }
+         }
+ 
+         /// <summary>
+         /// Write named string array.
+         /// </summary>
+         /// <param name="fieldName">Field name.</param>
+         /// <param name="val">String array.</param>
+         public void WriteStringArray(string fieldName, string[] val)
+         {
+             WriteFieldId(fieldName, PU.TypeArrayString);
+ 
+             if (val == null)
+                 WriteNullField();
+             else
+             {
+                 int pos = SkipFieldLength();
+ 
+                 _stream.WriteByte(PU.TypeArrayString);
+                 PU.WriteStringArray(val, _stream);
+ 
+                 WriteFieldLength(_stream, pos);
+             }
+         }
+ 
+         /// <summary>
+         /// Write string array.
+         /// </summary>
+         /// <param name="val">String array.</param>
+         public void WriteStringArray(string[] val)
+         {
+             if (val == null)
+                 WriteNullRawField();
+             else
+             {
+                 _stream.WriteByte(PU.TypeArrayString);
+                 PU.WriteStringArray(val, _stream);
+             }
+         }
+ 
+         /// <summary>
+         /// Write named GUID value.
+         /// </summary>
+         /// <param name="fieldName">Field name.</param>
+         /// <param name="val">GUID value.</param>
+         public void WriteGuid(string fieldName, Guid? val)
+         {
+             WriteFieldId(fieldName, PU.TypeGuid);
+ 
+             if (val == null)
+                 WriteNullField();
+             else
+             {
+                 _stream.WriteInt(PU.LengthTypeId + 16);
+ 
+                 _stream.WriteByte(PU.TypeGuid);
+                 PU.WriteGuid(val.Value, _stream);
+             }
+         }
+ 
+         /// <summary>
+         /// Write GUID value.
+         /// </summary>
+         /// <param name="val">GUID value.</param>
+         public void WriteGuid(Guid? val)
+         {
+             if (val == null)
+                 WriteNullRawField();
+             else
+             {
+                 _stream.WriteByte(PU.TypeGuid);
+                 PU.WriteGuid(val.Value, _stream);
+             }
+         }
+ 
+         /// <summary>
+         /// Write named GUID array.
+         /// </summary>
+         /// <param name="fieldName">Field name.</param>
+         /// <param name="val">GUID array.</param>
+         public void WriteGuidArray(string fieldName, Guid?[] val)
+         {
+             WriteFieldId(fieldName, PU.TypeArrayGuid);
+ 
+             if (val == null)
+                 WriteNullField();
+             else
+             {
+                 int pos = SkipFieldLength();
+ 
+                 _stream.WriteByte(PU.TypeArrayGuid);
+                 PU.WriteGuidArray(val, _stream);
+ 
+                 WriteFieldLength(_stream, pos);
+             }
+         }
+ 
+         /// <summary>
+         /// Write GUID array.
+         /// </summary>
+         /// <param name="val">GUID array.</param>
+         public void WriteGuidArray(Guid?[] val)
+         {
+             if (val == null)
+                 WriteNullRawField();
+             else
+             {
+                 _stream.WriteByte(PU.TypeArrayGuid);
+                 PU.WriteGuidArray(val, _stream);
+             }
+         }
+ 
+         /// <summary>
+         /// Write named enum value.
+         /// </summary>
+         /// <typeparam name="T"></typeparam>
+         /// <param name="fieldName">Field name.</param>
+         /// <param name="val">Enum value.</param>
+         public void WriteEnum<T>(string fieldName, T val)
+         {
+             WriteFieldId(fieldName, PU.TypeEnum);
+ 
+             _stream.WriteInt(PU.LengthTypeId + 16);
+ 
+             _stream.WriteByte(PU.TypeEnum);
+             PortableUtils.WriteEnum(_stream, (Enum)(object)val);
+         }
+ 
+         /// <summary>
+         /// Write enum value.
+         /// </summary>
+         /// <typeparam name="T"></typeparam>
+         /// <param name="val">Enum value.</param>
+         public void WriteEnum<T>(T val)
+         {
+             _stream.WriteByte(PU.TypeEnum);
+             PortableUtils.WriteEnum(_stream, (Enum)(object)val);
+         }
+ 
+         /// <summary>
+         /// Write named enum array.
+         /// </summary>
+         /// <typeparam name="T"></typeparam>
+         /// <param name="fieldName">Field name.</param>
+         /// <param name="val">Enum array.</param>
+         public void WriteEnumArray<T>(string fieldName, T[] val)
+         {
+             WriteFieldId(fieldName, PU.TypeArrayEnum);
+ 
+             if (val == null)
+                 WriteNullField();
+             else
+             {
+                 int pos = SkipFieldLength();
+ 
+                 _stream.WriteByte(PU.TypeArrayEnum);
+                 PortableUtils.WriteArray(val, this, true);
+ 
+                 WriteFieldLength(_stream, pos);
+             }
+         }
+ 
+         /// <summary>
+         /// Write enum array.
+         /// </summary>
+         /// <typeparam name="T"></typeparam>
+         /// <param name="val">Enum array.</param>
+         public void WriteEnumArray<T>(T[] val)
+         {
+             if (val == null)
+                 WriteNullRawField();
+             else
+             {
+                 _stream.WriteByte(PU.TypeArrayEnum);
+                 PortableUtils.WriteArray(val, this, true);
+             }
+         }
+ 
+         /// <summary>
+         /// Write named object value.
+         /// </summary>
+         /// <typeparam name="T"></typeparam>
+         /// <param name="fieldName">Field name.</param>
+         /// <param name="val">Object value.</param>
+         public void WriteObject<T>(string fieldName, T val)
+         {
+             WriteFieldId(fieldName, PU.TypeObject);
+ 
+             if (val == null)
+                 WriteNullField();
+             else
+             {
+                 int pos = SkipFieldLength();
+ 
+                 Write(val);
+ 
+                 WriteFieldLength(_stream, pos);
+             }
+         }
+ 
+         /// <summary>
+         /// Write object value.
+         /// </summary>
+         /// <typeparam name="T"></typeparam>
+         /// <param name="val">Object value.</param>
+         public void WriteObject<T>(T val)
+         {
+             Write(val);
+         }
+ 
+         /// <summary>
+         /// Write named object array.
+         /// </summary>
+         /// <typeparam name="T"></typeparam>
+         /// <param name="fieldName">Field name.</param>
+         /// <param name="val">Object array.</param>
+         public void WriteObjectArray<T>(string fieldName, T[] val)
+         {
+             WriteFieldId(fieldName, PU.TypeArray);
+ 
+             if (val == null)
+                 WriteNullField();
+             else
+             {
+                 int pos = SkipFieldLength();
+ 
+                 _stream.WriteByte(PU.TypeArray);
+                 PortableUtils.WriteArray(val, this, true);
+ 
+                 WriteFieldLength(_stream, pos);
+             }
+         }
+ 
+         /// <summary>
+         /// Write object array.
+         /// </summary>
+         /// <typeparam name="T"></typeparam>
+         /// <param name="val">Object array.</param>
+         public void WriteObjectArray<T>(T[] val)
+         {
+             if (val == null)
+                 WriteNullRawField();
+             else
+             {
+                 _stream.WriteByte(PU.TypeArray);
+                 PortableUtils.WriteArray(val, this, true);
+             }
+         }
+ 
+         /// <summary>
+         /// Write named collection.
+         /// </summary>
+         /// <param name="fieldName">Field name.</param>
+         /// <param name="val">Collection.</param>
+         public void WriteCollection(string fieldName, ICollection val)
+         {
+             WriteFieldId(fieldName, PU.TypeCollection);
+ 
+             if (val == null)
+                 WriteNullField();
+             else
+             {
+                 int pos = SkipFieldLength();
+ 
+                 Write(val);
+ 
+                 WriteFieldLength(_stream, pos);
+             }
+         }
+ 
+         /// <summary>
+         /// Write collection.
+         /// </summary>
+         /// <param name="val">Collection.</param>
+         public void WriteCollection(ICollection val)
+         {
+             Write(val);
+         }
+ 
+         /// <summary>
+         /// Write named generic collection.
+         /// </summary>
+         /// <typeparam name="T"></typeparam>
+         /// <param name="fieldName">Field name.</param>
+         /// <param name="val">Collection.</param>
+         public void WriteGenericCollection<T>(string fieldName, 
ICollection<T> val)
+         {
+             WriteFieldId(fieldName, PU.TypeCollection);
+ 
+             if (val == null)
+                 WriteNullField();
+             else
+             {
+                 int pos = SkipFieldLength();
+ 
+                 Write(val);
+ 
+                 WriteFieldLength(_stream, pos);
+             }
+         }
+ 
+         /// <summary>
+         /// Write generic collection.
+         /// </summary>
+         /// <typeparam name="T"></typeparam>
+         /// <param name="val">Collection.</param>
+         public void WriteGenericCollection<T>(ICollection<T> val)
+         {
+             Write(val);
+         }
+ 
+         /// <summary>
+         /// Write named dictionary.
+         /// </summary>
+         /// <param name="fieldName">Field name.</param>
+         /// <param name="val">Dictionary.</param>
+         public void WriteDictionary(string fieldName, IDictionary val)
+         {
+             WriteFieldId(fieldName, PU.TypeDictionary);
+ 
+             if (val == null)
+                 WriteNullField();
+             else
+             {
+                 int pos = SkipFieldLength();
+ 
+                 Write(val);
+ 
+                 WriteFieldLength(_stream, pos);
+             }
+         }
+ 
+         /// <summary>
+         /// Write dictionary.
+         /// </summary>
+         /// <param name="val">Dictionary.</param>
+         public void WriteDictionary(IDictionary val)
+         {
+             Write(val);
+         }
+ 
+         /// <summary>
+         /// Write named generic dictionary.
+         /// </summary>
+         /// <param name="fieldName">Field name.</param>
+         /// <param name="val">Dictionary.</param>
+         public void WriteGenericDictionary<TK, TV>(string fieldName, 
IDictionary<TK, TV> val)
+         {
+             WriteFieldId(fieldName, PU.TypeDictionary);
+ 
+             if (val == null)
+                 WriteNullField();
+             else
+             {
+                 int pos = SkipFieldLength();
+ 
+                 Write(val);
+ 
+                 WriteFieldLength(_stream, pos);
+             }
+         }
+ 
+         /// <summary>
+         /// Write generic dictionary.
+         /// </summary>
+         /// <param name="val">Dictionary.</param>
+         public void WriteGenericDictionary<TK, TV>(IDictionary<TK, TV> val)
+         {
+             Write(val);
+         }
+ 
+         /// <summary>
+         /// Write NULL field.
+         /// </summary>
+         public void WriteNullField()
+         {
+             _stream.WriteInt(1);
+             _stream.WriteByte(PU.HdrNull);
+         }
+ 
+         /// <summary>
+         /// Write NULL raw field.
+         /// </summary>
+         public void WriteNullRawField()
+         {
+             _stream.WriteByte(PU.HdrNull);
+         }
+ 
+         /// <summary>
+         /// Get raw writer.
+         /// </summary>
+         /// <returns>
+         /// Raw writer.
+         /// </returns>
+         public IPortableRawWriter GetRawWriter()
+         {
+             if (_curRawPos == 0)
+                 _curRawPos = _stream.Position;
+ 
+             return this;
+         }
+ 
+         /// <summary>
+         /// Set new builder.
+         /// </summary>
+         /// <param name="builder">Builder.</param>
+         /// <returns>Previous builder.</returns>
+         internal PortableBuilderImpl Builder(PortableBuilderImpl builder)
+         {
+             PortableBuilderImpl ret = _builder;
+ 
+             _builder = builder;
+ 
+             return ret;
+         }
+ 
+         /// <summary>
+         /// Constructor.
+         /// </summary>
+         /// <param name="marsh">Marshaller.</param>
+         /// <param name="stream">Stream.</param>
+         internal PortableWriterImpl(PortableMarshaller marsh, IPortableStream 
stream)
+         {
+             _marsh = marsh;
+             _stream = stream;
+         }
+ 
+         /// <summary>
+         /// Write object.
+         /// </summary>
+         /// <param name="obj">Object.</param>
+         public void Write<T>(T obj)
+         {
+             // Handle special case for null.
+             if (obj == null)
+             {
+                 _stream.WriteByte(PU.HdrNull);
+ 
+                 return;
+             }
+ 
+             // We use GetType() of a real object instead of typeof(T) to take 
advantage of 
+             // automatic Nullable'1 unwrapping.
+             Type type = obj.GetType();
+ 
+             // Handle common case when primitive is written.
+             if (type.IsPrimitive)
+             {
+                 WritePrimitive(obj, type);
+ 
+                 return;
+             }
+ 
+             // Handle special case for builder.
+             if (WriteBuilderSpecials(obj))
+                 return;
+ 
+             // Suppose that we faced normal object and perform descriptor 
lookup.
+             IPortableTypeDescriptor desc = _marsh.GetDescriptor(type);
+ 
+             if (desc != null)
+             {
+                 // Writing normal object.
+                 var pos = _stream.Position;
+ 
+                 // Dealing with handles.
+                 if (!(desc.Serializer is IPortableSystemTypeSerializer) && 
WriteHandle(pos, obj))
+                     return;
+ 
+                 // Write header.
+                 _stream.WriteByte(PU.HdrFull);
++                _stream.WriteByte(PU.ProtoVer);
+                 _stream.WriteBool(desc.UserType);
+                 _stream.WriteInt(desc.TypeId);
+                 _stream.WriteInt(obj.GetHashCode());
+ 
+                 // Skip length as it is not known in the first place.
+                 _stream.Seek(8, SeekOrigin.Current);
+ 
+                 // Preserve old frame.
+                 int oldTypeId = _curTypeId;
+                 IPortableNameMapper oldConverter = _curConverter;
+                 IPortableIdMapper oldMapper = _curMapper;
+                 long oldRawPos = _curRawPos;
+                 
+                 PortableStructure oldStruct = _curStruct;
+                 int oldStructPath = _curStructPath;
+                 int oldStructAction = _curStructAction;
+                 var oldStructUpdates = _curStructUpdates;
+ 
+                 // Push new frame.
+                 _curTypeId = desc.TypeId;
+                 _curConverter = desc.NameConverter;
+                 _curMapper = desc.Mapper;
+                 _curRawPos = 0;
+ 
+                 _curStruct = desc.TypeStructure;
+                 _curStructPath = 0;
+                 _curStructAction = 0;
+                 _curStructUpdates = null;
+ 
+                 // Write object fields.
+                 desc.Serializer.WritePortable(obj, this);
+ 
+                 // Calculate and write length.
+                 int len = _stream.Position - pos;
+ 
 -                _stream.WriteInt(pos + 10, len);
++                _stream.Seek(pos + PU.OffsetLen, SeekOrigin.Begin);
+ 
+                 if (_curRawPos != 0)
 -                    _stream.WriteInt(pos + 14, (int)(_curRawPos - pos));
++                    _stream.WriteInt(pos + PU.OffsetRaw, (int)(_curRawPos - 
pos));
+                 else
 -                    _stream.WriteInt(pos + 14, len);
++                    _stream.WriteInt(pos + PU.OffsetRaw, len);
+ 
+                 // Apply structure updates if any.
+                 if (_curStructUpdates != null)
+                 {
+                     desc.UpdateStructure(_curStruct, _curStructPath, 
_curStructUpdates);
+ 
+                     IPortableMetadataHandler metaHnd = 
_marsh.GetMetadataHandler(desc);
+ 
+                     if (metaHnd != null)
+                     {
+                         foreach (var u in _curStructUpdates)
+                             metaHnd.OnFieldWrite(u.FieldId, u.FieldName, 
u.FieldType);
+ 
+                         IDictionary<string, int> meta = 
metaHnd.OnObjectWriteFinished();
+ 
+                         if (meta != null)
+                             SaveMetadata(_curTypeId, desc.TypeName, 
desc.AffinityKeyFieldName, meta);
+                     }
+                 }
+ 
+                 // Restore old frame.
+                 _curTypeId = oldTypeId;
+                 _curConverter = oldConverter;
+                 _curMapper = oldMapper;
+                 _curRawPos = oldRawPos;
+ 
+                 _curStruct = oldStruct;
+                 _curStructPath = oldStructPath;
+                 _curStructAction = oldStructAction;
+                 _curStructUpdates = oldStructUpdates;
+             }
+             else
+             {
+                 // Are we dealing with a well-known type?
+                 PortableSystemWriteDelegate handler = 
PortableSystemHandlers.GetWriteHandler(type);
+ 
+                 if (handler != null)
+                     handler.Invoke(this, obj);
+                 else
+                 {
+                     // Last chance: is object seializable?
+                     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 + ']');
+                 }
+             }
+         }
+ 
+         /// <summary>
+         /// Write primitive type.
+         /// </summary>
+         /// <param name="val">Object.</param>
+         /// <param name="type">Type.</param>
+         public 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.
+ 
+             if (type == typeof(int))
+             {
+                 _stream.WriteByte(PU.TypeInt);
+                 _stream.WriteInt((int)(object)val);
+             }
+             else if (type == typeof(long))
+             {
+                 _stream.WriteByte(PU.TypeLong);
+                 _stream.WriteLong((long)(object)val);
+             }
+             else if (type == typeof(bool))
+             {
+                 _stream.WriteByte(PU.TypeBool);
+                 _stream.WriteBool((bool)(object)val);
+             }
+             else if (type == typeof(byte))
+             {
+                 _stream.WriteByte(PU.TypeByte);
+                 _stream.WriteByte((byte)(object)val);
+             }
+             else if (type == typeof(short))
+             {
+                 _stream.WriteByte(PU.TypeShort);
+                 _stream.WriteShort((short)(object)val);
+             }
+             else if (type == typeof (char))
+             {
+                 _stream.WriteByte(PU.TypeChar);
+                 _stream.WriteChar((char)(object)val);
+             }
+             else if (type == typeof(float))
+             {
+                 _stream.WriteByte(PU.TypeFloat);
+                 _stream.WriteFloat((float)(object)val);
+             }
+             else if (type == typeof(double))
+             {
+                 _stream.WriteByte(PU.TypeDouble);
+                 _stream.WriteDouble((double)(object)val);
+             }
+             else if (type == typeof(sbyte))
+             {
+                 sbyte val0 = (sbyte)(object)val;
+ 
+                 _stream.WriteByte(PU.TypeByte);
+                 _stream.WriteByte(*(byte*)&val0);
+             }
+             else if (type == typeof(ushort))
+             {
+                 ushort val0 = (ushort)(object)val;
+ 
+                 _stream.WriteByte(PU.TypeShort);
+                 _stream.WriteShort(*(short*)&val0);
+             }
+             else if (type == typeof(uint))
+             {
+                 uint val0 = (uint)(object)val;
+ 
+                 _stream.WriteByte(PU.TypeInt);
+                 _stream.WriteInt(*(int*)&val0);
+             }
+             else if (type == typeof(ulong))
+             {
+                 ulong val0 = (ulong)(object)val;
+ 
+                 _stream.WriteByte(PU.TypeLong);
+                 _stream.WriteLong(*(long*)&val0);
+             }
+             else
+                 throw new PortableException("Unsupported object type [type=" 
+ type.FullName + ", object=" + val + ']');
+         }
+ 
+         /// <summary>
+         /// Try writing object as special builder type.
+         /// </summary>
+         /// <param name="obj">Object.</param>
+         /// <returns>True if object was written, false otherwise.</returns>
+         private bool WriteBuilderSpecials<T>(T obj)
+         {
+             if (_builder != null)
+             {
+                 // Special case for portable object during build.
+                 PortableUserObject portObj = obj as PortableUserObject;
+ 
+                 if (portObj != null)
+                 {
+                     if (!WriteHandle(_stream.Position, portObj))
+                         _builder.ProcessPortable(_stream, portObj);
+ 
+                     return true;
+                 }
+ 
+                 // Special case for builder during build.
+                 PortableBuilderImpl portBuilder = obj as PortableBuilderImpl;
+ 
+                 if (portBuilder != null)
+                 {
+                     if (!WriteHandle(_stream.Position, portBuilder))
+                         _builder.ProcessBuilder(_stream, portBuilder);
+ 
+                     return true;
+                 }
+             }
+ 
+             return false;
+         }
+ 
+         /// <summary>
+         /// Add handle to handles map.
+         /// </summary>
+         /// <param name="pos">Position in stream.</param>
+         /// <param name="obj">Object.</param>
+         /// <returns><c>true</c> if object was written as handle.</returns>
+         private bool WriteHandle(long pos, object obj)
+         {
+             if (_hnds == null)
+             {
+                 // Cache absolute handle position.
+                 _hnds = new PortableHandleDictionary<object, long>(obj, pos);
+ 
+                 return false;
+             }
+ 
+             long hndPos;
+ 
+             if (!_hnds.TryGetValue(obj, out hndPos))
+             {
+                 // Cache absolute handle position.
+                 _hnds.Add(obj, pos);
+ 
+                 return false;
+             }
+ 
+             _stream.WriteByte(PU.HdrHnd);
+ 
+             // Handle is written as difference between position before header 
and handle position.
+             _stream.WriteInt((int)(pos - hndPos));
+ 
+             return true;
+         }
+ 
+         /// <summary>
+         /// Perform action with detached semantics.
+         /// </summary>
+         /// <param name="a"></param>
+         internal void WithDetach(Action<PortableWriterImpl> a)
+         {
+             if (_detaching)
+                 a(this);
+             else
+             {
+                 _detaching = true;
+ 
+                 PortableHandleDictionary<object, long> oldHnds = _hnds;
+                 _hnds = null;
+ 
+                 try
+                 {
+                     a(this);
+                 }
+                 finally
+                 {
+                     _detaching = false;
+ 
+                     if (oldHnds != null)
+                     {
+                         // Merge newly recorded handles with old ones and 
restore old on the stack.
+                         // Otherwise we can use current handles right away.
+                         if (_hnds != null)
+                             oldHnds.Merge(_hnds);
+ 
+                         _hnds = oldHnds;
+                     }
+                 }
+             }
+         }
+ 
+         /// <summary>
+         /// Stream.
+         /// </summary>
+         internal IPortableStream Stream
+         {
+             get { return _stream; }
+         }
+ 
+         /// <summary>
+         /// Gets collected metadatas.
+         /// </summary>
+         /// <returns>Collected metadatas (if any).</returns>
+         internal IDictionary<int, IPortableMetadata> Metadata()
+         {
+             return _metas;
+         }
+ 
+         /// <summary>
+         /// Check whether the given object is portable, i.e. it can be 
+         /// serialized with portable marshaller.
+         /// </summary>
+         /// <param name="obj">Object.</param>
+         /// <returns>True if portable.</returns>
+         internal bool IsPortable(object obj)
+         {
+             if (obj != null)
+             {
+                 Type type = obj.GetType();
+ 
+                 // We assume object as portable only in case it has 
descriptor.
+                 // Collections, Enums and non-primitive arrays do not have 
descriptors
+                 // and this is fine here because we cannot know whether their 
members
+                 // are portable.
+                 return _marsh.GetDescriptor(type) != null || 
PortableSystemHandlers.GetWriteHandler(type) != null;
+             }
+ 
+             return true;
+         }
+         
+         /// <summary>
+         /// Write field ID.
+         /// </summary>
+         /// <param name="fieldName">Field name.</param>
+         /// <param name="fieldTypeId">Field type ID.</param>
+         private void WriteFieldId(string fieldName, byte fieldTypeId)
+         {
+             if (_curRawPos != 0)
+                 throw new PortableException("Cannot write named fields after 
raw data is written.");
+ 
+             int action = _curStructAction++;
+ 
+             int fieldId;
+ 
+             if (_curStructUpdates == null)
+             {
+                 fieldId = _curStruct.GetFieldId(fieldName, fieldTypeId, ref 
_curStructPath, action);
+ 
+                 if (fieldId == 0)
+                     fieldId = GetNewFieldId(fieldName, fieldTypeId, action);
+             }
+             else
+                 fieldId = GetNewFieldId(fieldName, fieldTypeId, action);
+ 
+             _stream.WriteInt(fieldId);
+         }
+ 
+         /// <summary>
+         /// Get ID for the new field and save structure update.
+         /// </summary>
+         /// <param name="fieldName">Field name.</param>
+         /// <param name="fieldTypeId">Field type ID.</param>
+         /// <param name="action">Action index.</param>
+         /// <returns>Field ID.</returns>
+         private int GetNewFieldId(string fieldName, byte fieldTypeId, int 
action)
+         {
+             int fieldId = PU.FieldId(_curTypeId, fieldName, _curConverter, 
_curMapper);
+ 
+             if (_curStructUpdates == null)
+                 _curStructUpdates = new List<PortableStructureUpdate>();
+ 
+             _curStructUpdates.Add(new PortableStructureUpdate(fieldName, 
fieldId, fieldTypeId, action));
+ 
+             return fieldId;
+         }
+ 
+         /// <summary>
+         /// Skip field lenght and return position where it is to be written.
+         /// </summary>
+         /// <returns></returns>
+         private int SkipFieldLength()
+         {
+             int pos = _stream.Position;
+ 
+             _stream.Seek(4, SeekOrigin.Current);
+ 
+             return pos;
+         }
+ 
+         /// <summary>
+         /// Write field length.
+         /// </summary>
+         /// <param name="stream">Stream.</param>
+         /// <param name="pos">Position where length should reside</param>
+         private static void WriteFieldLength(IPortableStream stream, int pos)
+         {
+             // Length is is a difference between current position and 
previously recorder 
+             // length placeholder position minus 4 bytes for the length 
itself.
+             stream.WriteInt(pos, stream.Position - pos - 4);
+         }
+         
+         /// <summary>
+         /// Saves metadata for this session.
+         /// </summary>
+         /// <param name="typeId">Type ID.</param>
+         /// <param name="typeName">Type name.</param>
+         /// <param name="affKeyFieldName">Affinity key field name.</param>
+         /// <param name="fields">Fields metadata.</param>
+         internal void SaveMetadata(int typeId, string typeName, string 
affKeyFieldName, IDictionary<string, int> fields)
+         {
+             if (_metas == null)
+             {
+                 PortableMetadataImpl meta =
+                     new PortableMetadataImpl(typeId, typeName, fields, 
affKeyFieldName);
+ 
+                 _metas = new Dictionary<int, IPortableMetadata>(1);
+ 
+                 _metas[typeId] = meta;
+             }
+             else
+             {
+                 IPortableMetadata meta;
+ 
+                 if (_metas.TryGetValue(typeId, out meta))
+                 {
+                     IDictionary<string, int> existingFields = 
((PortableMetadataImpl)meta).FieldsMap();
+ 
+                     foreach (KeyValuePair<string, int> field in fields)
+                     {
+                         if (!existingFields.ContainsKey(field.Key))
+                             existingFields[field.Key] = field.Value;
+                     }
+                 }
+                 else
+                     _metas[typeId] = new PortableMetadataImpl(typeId, 
typeName, fields, affKeyFieldName);
+             }
+         }
+     }
+ }

http://git-wip-us.apache.org/repos/asf/ignite/blob/ec58b87c/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Portable/PortablesImpl.cs
----------------------------------------------------------------------
diff --cc 
modules/platforms/dotnet/Apache.Ignite.Core/Impl/Portable/PortablesImpl.cs
index 0000000,5b73171..451386b
mode 000000,100644..100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Portable/PortablesImpl.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Portable/PortablesImpl.cs
@@@ -1,0 -1,192 +1,193 @@@
+ /*
+  * 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.Collections.Generic;
+     using System.IO;
+     using Apache.Ignite.Core.Common;
+     using Apache.Ignite.Core.Impl.Common;
+     using Apache.Ignite.Core.Impl.Portable.IO;
+     using Apache.Ignite.Core.Portable;
+ 
+     /// <summary>
+     /// Portables implementation.
+     /// </summary>
+     internal class PortablesImpl : IPortables
+     {
+         /** Owning grid. */
+         private readonly PortableMarshaller _marsh;
+ 
+         /// <summary>
+         /// Constructor.
+         /// </summary>
+         /// <param name="marsh">Marshaller.</param>
+         internal PortablesImpl(PortableMarshaller marsh)
+         {
+             _marsh = marsh;
+         }
+ 
+         /** <inheritDoc /> */
+         public T ToPortable<T>(object obj)
+         {
+             if (obj is IPortableObject)
+                 return (T)obj;
+ 
+             IPortableStream stream = new PortableHeapStream(1024);
+ 
+             // Serialize.
+             PortableWriterImpl writer = _marsh.StartMarshal(stream);
+ 
+             try
+             {
+                 writer.Write(obj);
+             }
+             finally
+             {
+                 // Save metadata.
+                 _marsh.FinishMarshal(writer);
+             }
+ 
+             // Deserialize.
+             stream.Seek(0, SeekOrigin.Begin);
+ 
+             return _marsh.Unmarshal<T>(stream, PortableMode.ForcePortable);
+         }
+ 
+         /** <inheritDoc /> */
+         public IPortableBuilder GetBuilder(Type type)
+         {
+             IgniteArgumentCheck.NotNull(type, "type");
+ 
+             IPortableTypeDescriptor desc = _marsh.GetDescriptor(type);
+ 
+             if (desc == null)
+                 throw new IgniteException("Type is not portable (add it to 
PortableConfiguration): " + 
+                     type.FullName);
+ 
+             return Builder0(null, PortableFromDescriptor(desc), desc);
+         }
+ 
+         /** <inheritDoc /> */
+         public IPortableBuilder GetBuilder(string typeName)
+         {
+             IgniteArgumentCheck.NotNullOrEmpty(typeName, "typeName");
+ 
+             IPortableTypeDescriptor desc = _marsh.GetDescriptor(typeName);
+             
+             return Builder0(null, PortableFromDescriptor(desc), desc);
+         }
+ 
+         /** <inheritDoc /> */
+         public IPortableBuilder GetBuilder(IPortableObject obj)
+         {
+             IgniteArgumentCheck.NotNull(obj, "obj");
+ 
+             PortableUserObject obj0 = obj as PortableUserObject;
+ 
+             if (obj0 == null)
+                 throw new ArgumentException("Unsupported object type: " + 
obj.GetType());
+ 
+             IPortableTypeDescriptor desc = _marsh.GetDescriptor(true, 
obj0.TypeId);
+             
+             return Builder0(null, obj0, desc);
+         }
+ 
+         /** <inheritDoc /> */
+         public int GetTypeId(string typeName)
+         {
+             IgniteArgumentCheck.NotNullOrEmpty(typeName, "typeName");
+ 
+             return Marshaller.GetDescriptor(typeName).TypeId;
+         }
+ 
+         /** <inheritDoc /> */
+         public ICollection<IPortableMetadata> GetMetadata()
+         {
+             return Marshaller.Ignite.ClusterGroup.Metadata();
+         }
+ 
+         /** <inheritDoc /> */
+         public IPortableMetadata GetMetadata(int typeId)
+         {
+             return Marshaller.GetMetadata(typeId);
+         }
+ 
+         /** <inheritDoc /> */
+         public IPortableMetadata GetMetadata(string typeName)
+         {
+             IgniteArgumentCheck.NotNullOrEmpty(typeName, "typeName");
+ 
+             return GetMetadata(GetTypeId(typeName));
+         }
+ 
+         /** <inheritDoc /> */
+         public IPortableMetadata GetMetadata(Type type)
+         {
+             IgniteArgumentCheck.NotNull(type, "type");
+ 
+             var desc = Marshaller.GetDescriptor(type);
+ 
+             return desc == null ? null : Marshaller.GetMetadata(desc.TypeId);
+         }
+ 
+         /// <summary>
+         /// Marshaller.
+         /// </summary>
+         internal PortableMarshaller Marshaller
+         {
+             get
+             {
+                 return _marsh;
+             }
+         }
+ 
+         /// <summary>
+         /// Create empty portable object from descriptor.
+         /// </summary>
+         /// <param name="desc">Descriptor.</param>
+         /// <returns>Empty portable object.</returns>
+         private PortableUserObject 
PortableFromDescriptor(IPortableTypeDescriptor desc)
+         {
+             PortableHeapStream stream = new PortableHeapStream(18);
+ 
+             stream.WriteByte(PortableUtils.HdrFull);
++            stream.WriteByte(PortableUtils.ProtoVer);
+             stream.WriteBool(true);
+             stream.WriteInt(desc.TypeId);
+             stream.WriteInt(0); // Hash.
+             stream.WriteInt(PortableUtils.FullHdrLen); // Length.
+             stream.WriteInt(PortableUtils.FullHdrLen); // Raw data offset.
+ 
+             return new PortableUserObject(_marsh, stream.InternalArray, 0, 
desc.TypeId, 0);
+         }
+ 
+         /// <summary>
+         /// Internal builder creation routine.
+         /// </summary>
+         /// <param name="parent">Parent builder.</param>
+         /// <param name="obj">Portable object.</param>
+         /// <param name="desc">Type descriptor.</param>
+         /// <returns>Builder.</returns>
+         private PortableBuilderImpl Builder0(PortableBuilderImpl parent, 
PortableUserObject obj, 
+             IPortableTypeDescriptor desc)
+         {
+             return new PortableBuilderImpl(this, parent, obj, desc);
+         }
+     }
+ }

Reply via email to