You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by sb...@apache.org on 2017/05/29 07:18:35 UTC

[19/30] ignite git commit: IGNITE-4575: Improved binary enums support. This closes #1968.

http://git-wip-us.apache.org/repos/asf/ignite/blob/b5c7b6f5/modules/platforms/dotnet/Apache.Ignite.Core/Binary/IBinaryObject.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Binary/IBinaryObject.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Binary/IBinaryObject.cs
index 841972d..7ab69e9 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Binary/IBinaryObject.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Binary/IBinaryObject.cs
@@ -65,6 +65,14 @@ namespace Apache.Ignite.Core.Binary
         int EnumValue { get; }
 
         /// <summary>
+        /// Gets the name of the underlying enum value.
+        /// </summary>
+        /// <value>
+        /// The name of the enum value.
+        /// </value>
+        string EnumName { get; }
+
+        /// <summary>
         /// Creates a new <see cref="IBinaryObjectBuilder"/> based on this object.
         /// <para />
         /// This is equivalent to <see cref="IBinary.GetBuilder(IBinaryObject)"/>.

http://git-wip-us.apache.org/repos/asf/ignite/blob/b5c7b6f5/modules/platforms/dotnet/Apache.Ignite.Core/Binary/IBinaryType.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Binary/IBinaryType.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Binary/IBinaryType.cs
index bec863f..df6693d 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Binary/IBinaryType.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Binary/IBinaryType.cs
@@ -61,5 +61,11 @@ namespace Apache.Ignite.Core.Binary
         /// Gets the type identifier.
         /// </summary>
         int TypeId { get; }
+
+        /// <summary>
+        /// Gets the enum values.
+        /// Only valid when <see cref="IsEnum"/> is true.
+        /// </summary>
+        IEnumerable<IBinaryObject> GetEnumValues();
     }
 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/b5c7b6f5/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/Binary.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/Binary.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/Binary.cs
index 4f3156c..bcf6c2d 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/Binary.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/Binary.cs
@@ -19,6 +19,7 @@ namespace Apache.Ignite.Core.Impl.Binary
 {
     using System;
     using System.Collections.Generic;
+    using System.Diagnostics;
     using System.IO;
     using Apache.Ignite.Core.Binary;
     using Apache.Ignite.Core.Common;
@@ -165,7 +166,8 @@ namespace Apache.Ignite.Core.Impl.Binary
         public IBinaryObject BuildEnum(Type type, int value)
         {
             IgniteArgumentCheck.NotNull(type, "type");
-            IgniteArgumentCheck.Ensure(type.IsEnum, "type", "Type should be an Enum.");
+            IgniteArgumentCheck.Ensure(BinaryUtils.IsIgniteEnum(type), "type", 
+                "Type should be an Enum.");
             
             var desc = Marshaller.GetDescriptor(type);
 
@@ -176,15 +178,53 @@ namespace Apache.Ignite.Core.Impl.Binary
             return new BinaryEnum(desc.TypeId, value, Marshaller);
         }
 
+        /** <inheritDoc /> */
+        public IBinaryObject BuildEnum(string typeName, string valueName)
+        {
+            IgniteArgumentCheck.NotNullOrEmpty(typeName, "typeName");
+            IgniteArgumentCheck.NotNullOrEmpty(valueName, "valueName");
+
+            var desc = Marshaller.GetDescriptor(typeName);
+
+            IgniteArgumentCheck.Ensure(desc.IsEnum, "typeName", "Type should be an Enum.");
+
+            _marsh.PutBinaryType(desc);
+
+            var value = GetEnumValueAsInt(typeName, valueName, desc);
+
+            return new BinaryEnum(desc.TypeId, value, Marshaller);
+        }
+
+        /** <inheritDoc /> */
+        public IBinaryObject BuildEnum(Type type, string valueName)
+        {
+            IgniteArgumentCheck.NotNullOrEmpty(valueName, "valueName");
+
+            var desc = Marshaller.GetDescriptor(type);
+
+            IgniteArgumentCheck.Ensure(desc.IsEnum, "typeName", "Type should be an Enum.");
+
+            _marsh.PutBinaryType(desc);
+
+            var value = GetEnumValueAsInt(type.ToString(), valueName, desc);
+
+            return new BinaryEnum(desc.TypeId, value, Marshaller);
+        }
+
+        /** <inheritDoc /> */
+        public IBinaryType RegisterEnum(string typeName, IEnumerable<KeyValuePair<string, int>> values)
+        {
+            IgniteArgumentCheck.NotNullOrEmpty(typeName, "typeName");
+
+            return Marshaller.Ignite.BinaryProcessor.RegisterEnum(typeName, values);
+        }
+
         /// <summary>
         /// Marshaller.
         /// </summary>
         internal Marshaller Marshaller
         {
-            get
-            {
-                return _marsh;
-            }
+            get { return _marsh; }
         }
 
         /// <summary>
@@ -199,5 +239,22 @@ namespace Apache.Ignite.Core.Impl.Binary
         {
             return new BinaryObjectBuilder(this, parent, obj, desc);
         }
+
+        /// <summary>
+        /// Gets the enum value as int.
+        /// </summary>
+        private int GetEnumValueAsInt(string typeName, string valueName, IBinaryTypeDescriptor desc)
+        {
+            var type = Marshaller.GetBinaryType(desc.TypeId);
+
+            var value = type.GetEnumValue(valueName);
+
+            IgniteArgumentCheck.Ensure(value != null, "valueName",
+                string.Format("Enum '{0}' does not have a value {1}", typeName, valueName));
+
+            Debug.Assert(value.HasValue);
+
+            return value.Value;
+        }
     }
 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/b5c7b6f5/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryEnum.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryEnum.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryEnum.cs
index 710cf17..2bc4bdf 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryEnum.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryEnum.cs
@@ -88,6 +88,12 @@ namespace Apache.Ignite.Core.Impl.Binary
         }
 
         /** <inheritdoc /> */
+        public string EnumName
+        {
+            get { return _marsh.GetBinaryType(_typeId).GetEnumName(_enumValue); }
+        }
+
+        /** <inheritdoc /> */
         public IBinaryObjectBuilder ToBuilder()
         {
             throw new NotSupportedException("Builder cannot be created for enum.");
@@ -136,11 +142,8 @@ namespace Apache.Ignite.Core.Impl.Binary
                 return string.Format("BinaryEnum [typeId={0}, enumValue={1}]", _typeId, _enumValue);
             }
 
-            var desc = _marsh.GetDescriptor(true, _typeId);
-            var enumValueName = desc != null && desc.Type != null ? Enum.GetName(desc.Type, _enumValue) : null;
-
             return string.Format("{0} [typeId={1}, enumValue={2}, enumValueName={3}]",
-                meta.TypeName, _typeId, _enumValue, enumValueName);
+                meta.TypeName, _typeId, _enumValue, EnumName);
         }
     }
 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/b5c7b6f5/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryObject.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryObject.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryObject.cs
index 480e0e6..8c5cee6 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryObject.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryObject.cs
@@ -131,7 +131,18 @@ namespace Apache.Ignite.Core.Impl.Binary
         {
             get
             {
-                throw new NotSupportedException("IBinaryObject.Value is only supported for enums. " +
+                throw new NotSupportedException("IBinaryObject.EnumValue is only supported for enums. " +
+                    "Check IBinaryObject.GetBinaryType().IsEnum property before accessing Value.");
+            }
+        }
+
+        /** <inheritdoc /> */
+        [ExcludeFromCodeCoverage]
+        public string EnumName
+        {
+            get
+            {
+                throw new NotSupportedException("IBinaryObject.EnumName is only supported for enums. " +
                     "Check IBinaryObject.GetBinaryType().IsEnum property before accessing Value.");
             }
         }

http://git-wip-us.apache.org/repos/asf/ignite/blob/b5c7b6f5/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryProcessor.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryProcessor.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryProcessor.cs
index 72a1d5b..f48bcc0 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryProcessor.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryProcessor.cs
@@ -24,7 +24,7 @@ namespace Apache.Ignite.Core.Impl.Binary
     using Apache.Ignite.Core.Impl.Unmanaged;
 
     /// <summary>
-    /// Binary metadata processor.
+    /// Binary metadata processor, delegates to PlatformBinaryProcessor in Java.
     /// </summary>
     internal class BinaryProcessor : PlatformTarget
     {
@@ -38,7 +38,8 @@ namespace Apache.Ignite.Core.Impl.Binary
             PutMeta = 3,
             GetSchema = 4,
             RegisterType = 5,
-            GetType = 6
+            GetType = 6,
+            RegisterEnum = 7
         }
 
         /// <summary>
@@ -54,9 +55,9 @@ namespace Apache.Ignite.Core.Impl.Binary
         /// <summary>
         /// Gets metadata for specified type.
         /// </summary>
-        public IBinaryType GetBinaryType(int typeId)
+        public BinaryType GetBinaryType(int typeId)
         {
-            return DoOutInOp<IBinaryType>((int) Op.GetMeta,
+            return DoOutInOp((int) Op.GetMeta,
                 writer => writer.WriteInt(typeId),
                 stream =>
                 {
@@ -126,8 +127,27 @@ namespace Apache.Ignite.Core.Impl.Binary
                         w.WriteInt(field.Value.FieldId);
                     }
 
+                    // Enum data
                     w.WriteBoolean(meta.IsEnum);
 
+                    if (meta.IsEnum)
+                    {
+                        if (meta.EnumValuesMap != null)
+                        {
+                            w.WriteInt(meta.EnumValuesMap.Count);
+
+                            foreach (var pair in meta.EnumValuesMap)
+                            {
+                                w.WriteString(pair.Key);
+                                w.WriteInt(pair.Value);
+                            }
+                        }
+                        else
+                        {
+                            w.WriteInt(0);
+                        }
+                    }
+
                     // Send schemas
                     var desc = meta.Descriptor;
                     Debug.Assert(desc != null);
@@ -175,6 +195,43 @@ namespace Apache.Ignite.Core.Impl.Binary
         }
 
         /// <summary>
+        /// Registers the enum.
+        /// </summary>
+        /// <param name="typeName">Name of the type.</param>
+        /// <param name="values">The values.</param>
+        /// <returns>Resulting binary type.</returns>
+        public BinaryType RegisterEnum(string typeName, IEnumerable<KeyValuePair<string, int>> values)
+        {
+            Debug.Assert(typeName != null);
+
+            return DoOutInOp((int) Op.RegisterEnum, w =>
+            {
+                w.WriteString(typeName);
+
+                if (values == null)
+                {
+                    w.WriteInt(0);
+                }
+                else
+                {
+                    var countPos = w.Stream.Position;
+                    w.WriteInt(0);
+                    var count = 0;
+
+                    foreach (var enumPair in values)
+                    {
+                        w.WriteString(enumPair.Key);
+                        w.WriteInt(enumPair.Value);
+
+                        count++;
+                    }
+
+                    w.Stream.WriteInt(countPos, count);
+                }
+            }, s => s.ReadBool() ? new BinaryType(Marshaller.StartUnmarshal(s)) : null);
+        }
+
+        /// <summary>
         /// Gets the type by id.
         /// </summary>
         /// <param name="id">The identifier.</param>

http://git-wip-us.apache.org/repos/asf/ignite/blob/b5c7b6f5/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryReader.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryReader.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryReader.cs
index a5c6814..73a0456 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryReader.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryReader.cs
@@ -401,6 +401,7 @@ namespace Apache.Ignite.Core.Impl.Binary
                     return default(T);
 
                 case BinaryUtils.TypeEnum:
+                case BinaryUtils.TypeBinaryEnum:
                     // Never read enums in binary mode when reading a field (we do not support half-binary objects)
                     return ReadEnum0<T>(this, false);  
 
@@ -411,9 +412,9 @@ namespace Apache.Ignite.Core.Impl.Binary
                     return ReadObject<T>(); 
 
                 default:
-                    throw new BinaryObjectException(
-                        string.Format("Invalid header on enum deserialization. Expected: {0} or {1} but was: {2}",
-                            BinaryUtils.TypeEnum, BinaryUtils.HdrFull, hdr));
+                    throw new BinaryObjectException(string.Format(
+                        "Invalid header on enum deserialization. Expected: {0} or {1} or {2} but was: {3}",
+                            BinaryUtils.TypeEnum, BinaryUtils.TypeBinaryEnum, BinaryUtils.HdrFull, hdr));
             }
         }
 
@@ -571,6 +572,7 @@ namespace Apache.Ignite.Core.Impl.Binary
                     return true;
 
                 case BinaryUtils.TypeEnum:
+                case BinaryUtils.TypeBinaryEnum:
                     res = ReadEnum0<T>(this, _mode != BinaryMode.Deserialize);
 
                     return true;
@@ -994,7 +996,9 @@ namespace Apache.Ignite.Core.Impl.Binary
             var enumValue = reader.ReadInt();
 
             if (!keepBinary)
+            {
                 return BinaryUtils.GetEnumValue<T>(enumValue, enumType, reader.Marshaller);
+            }
 
             return TypeCaster<T>.Cast(new BinaryEnum(enumType, enumValue, reader.Marshaller));
         }

http://git-wip-us.apache.org/repos/asf/ignite/blob/b5c7b6f5/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinarySystemHandlers.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinarySystemHandlers.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinarySystemHandlers.cs
index 1dfc3b6..95a0be3 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinarySystemHandlers.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinarySystemHandlers.cs
@@ -255,7 +255,7 @@ namespace Apache.Ignite.Core.Impl.Binary
                 if (elemType == typeof(Guid?))
                     return new BinarySystemWriteHandler<Guid?[]>(WriteGuidArray, true);
                 // Enums.
-                if (IsIntEnum(elemType) || elemType == typeof(BinaryEnum))
+                if (BinaryUtils.IsIgniteEnum(elemType) || elemType == typeof(BinaryEnum))
                     return new BinarySystemWriteHandler<object>(WriteEnumArray, true);
 
                 // Object array.
@@ -266,23 +266,6 @@ namespace Apache.Ignite.Core.Impl.Binary
         }
 
         /// <summary>
-        /// Determines whether specified type is an enum which fits into Int32.
-        /// </summary>
-        private static bool IsIntEnum(Type type)
-        {
-            if (!type.IsEnum)
-                return false;
-
-            var underlyingType = Enum.GetUnderlyingType(type);
-
-            return underlyingType == typeof(int) 
-                || underlyingType == typeof(short)
-                || underlyingType == typeof(ushort)
-                || underlyingType == typeof(byte)
-                || underlyingType == typeof(sbyte);
-        }
-
-        /// <summary>
         /// Find write handler for type.
         /// </summary>
         /// <param name="type">Type.</param>
@@ -294,10 +277,10 @@ namespace Apache.Ignite.Core.Impl.Binary
             if (TypeIds.TryGetValue(type, out res))
                 return res;
 
-            if (type.IsEnum)
+            if (BinaryUtils.IsIgniteEnum(type))
                 return BinaryUtils.TypeEnum;
 
-            if (type.IsArray && type.GetElementType().IsEnum)
+            if (type.IsArray && BinaryUtils.IsIgniteEnum(type.GetElementType()))
                 return BinaryUtils.TypeArrayEnum;
 
             return BinaryUtils.TypeObject;
@@ -545,7 +528,7 @@ namespace Apache.Ignite.Core.Impl.Binary
         {
             var binEnum = obj;
 
-            ctx.Stream.WriteByte(BinaryUtils.TypeEnum);
+            ctx.Stream.WriteByte(BinaryUtils.TypeBinaryEnum);
 
             ctx.WriteInt(binEnum.TypeId);
             ctx.WriteInt(binEnum.EnumValue);

http://git-wip-us.apache.org/repos/asf/ignite/blob/b5c7b6f5/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryUtils.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryUtils.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryUtils.cs
index a2783ba..2ac617e 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryUtils.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryUtils.cs
@@ -143,6 +143,9 @@ namespace Apache.Ignite.Core.Impl.Binary
         /** Type: enum array. */
         public const byte TypeArrayEnum = 29;
 
+        /** Type: binary enum. */
+        public const byte TypeBinaryEnum = 38;
+
         /** Type: native job holder. */
         public const byte TypeNativeJobHolder = 77;
 
@@ -1778,6 +1781,22 @@ namespace Apache.Ignite.Core.Impl.Binary
         }
 
         /// <summary>
+        /// Determines whether specified type is Ignite-compatible enum (value fits into 4 bytes).
+        /// </summary>
+        public static bool IsIgniteEnum(Type type)
+        {
+            Debug.Assert(type != null);
+
+            if (!type.IsEnum)
+                return false;
+
+            var enumType = Enum.GetUnderlyingType(type);
+
+            return enumType == typeof(int) || enumType == typeof(byte) || enumType == typeof(sbyte) 
+                || enumType == typeof(short) || enumType == typeof(ushort) || enumType == typeof(uint);
+        }
+
+        /// <summary>
         /// Creates and instance from the type name in reader.
         /// </summary>
         private static T CreateInstance<T>(BinaryReader reader)

http://git-wip-us.apache.org/repos/asf/ignite/blob/b5c7b6f5/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryWriter.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryWriter.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryWriter.cs
index 56774d4..a5fed48 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryWriter.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryWriter.cs
@@ -1468,7 +1468,7 @@ namespace Apache.Ignite.Core.Impl.Binary
             {
                 _metas = new Dictionary<int, BinaryType>(1)
                 {
-                    {desc.TypeId, new BinaryType(desc, fields)}
+                    {desc.TypeId, new BinaryType(desc, _marsh, fields)}
                 };
             }
             else
@@ -1478,7 +1478,7 @@ namespace Apache.Ignite.Core.Impl.Binary
                 if (_metas.TryGetValue(desc.TypeId, out meta))
                     meta.UpdateFields(fields);
                 else
-                    _metas[desc.TypeId] = new BinaryType(desc, fields);
+                    _metas[desc.TypeId] = new BinaryType(desc, _marsh, fields);
             }
         }
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/b5c7b6f5/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/Marshaller.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/Marshaller.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/Marshaller.cs
index ea2964a..8f12acf 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/Marshaller.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/Marshaller.cs
@@ -97,13 +97,13 @@ namespace Apache.Ignite.Core.Impl.Binary
 
             if (typeCfgs != null)
                 foreach (BinaryTypeConfiguration typeCfg in typeCfgs)
-                    AddUserType(cfg, typeCfg, typeResolver);
+                    AddUserType(typeCfg, typeResolver);
 
             var typeNames = _cfg.Types;
 
             if (typeNames != null)
                 foreach (string typeName in typeNames)
-                    AddUserType(cfg, new BinaryTypeConfiguration(typeName), typeResolver);
+                    AddUserType(new BinaryTypeConfiguration(typeName), typeResolver);
         }
 
         /// <summary>
@@ -289,14 +289,16 @@ namespace Apache.Ignite.Core.Impl.Binary
         /// </summary>
         /// <param name="typeId">Type ID.</param>
         /// <returns>Metadata or null.</returns>
-        public IBinaryType GetBinaryType(int typeId)
+        public BinaryType GetBinaryType(int typeId)
         {
             if (Ignite != null)
             {
-                IBinaryType meta = Ignite.BinaryProcessor.GetBinaryType(typeId);
+                var meta = Ignite.BinaryProcessor.GetBinaryType(typeId);
 
                 if (meta != null)
+                {
                     return meta;
+                }
             }
 
             return BinaryType.Empty;
@@ -314,7 +316,7 @@ namespace Apache.Ignite.Core.Impl.Binary
 
             if (Ignite != null)
             {
-                ICollection<BinaryType> metas = new[] {new BinaryType(desc)};
+                ICollection<BinaryType> metas = new[] {new BinaryType(desc, this)};
                 Ignite.BinaryProcessor.PutBinaryTypes(metas);
             }
         }
@@ -337,7 +339,8 @@ namespace Apache.Ignite.Core.Impl.Binary
                         IDictionary<int, BinaryTypeHolder> metas0 =
                             new Dictionary<int, BinaryTypeHolder>(_metas);
 
-                        holder = new BinaryTypeHolder(desc.TypeId, desc.TypeName, desc.AffinityKeyFieldName, desc.IsEnum);
+                        holder = new BinaryTypeHolder(desc.TypeId, desc.TypeName, desc.AffinityKeyFieldName, 
+                            desc.IsEnum, this);
 
                         metas0[desc.TypeId] = holder;
 
@@ -366,16 +369,7 @@ namespace Apache.Ignite.Core.Impl.Binary
         {
             foreach (var meta in newMetas)
             {
-                var mergeInfo = new Dictionary<int, Tuple<string, BinaryField>>(meta.GetFieldsMap().Count);
-
-                foreach (var fieldMeta in meta.GetFieldsMap())
-                {
-                    int fieldId = BinaryUtils.FieldId(meta.TypeId, fieldMeta.Key, null, null);
-
-                    mergeInfo[fieldId] = new Tuple<string, BinaryField>(fieldMeta.Key, fieldMeta.Value);
-                }
-
-                _metas[meta.TypeId].Merge(mergeInfo);
+                _metas[meta.TypeId].Merge(meta);
             }
         }
 
@@ -391,7 +385,9 @@ namespace Apache.Ignite.Core.Impl.Binary
             BinaryFullTypeDescriptor desc;
 
             if (!_typeToDesc.TryGetValue(type, out desc) || !desc.IsRegistered)
+            {
                 desc = RegisterType(type, desc);
+            }
 
             return desc;
         }
@@ -405,10 +401,14 @@ namespace Apache.Ignite.Core.Impl.Binary
         {
             BinaryFullTypeDescriptor desc;
 
-            return _typeNameToDesc.TryGetValue(typeName, out desc)
-                ? (IBinaryTypeDescriptor) desc
-                : new BinarySurrogateTypeDescriptor(_cfg,
-                    GetTypeId(typeName, _cfg.IdMapper), typeName);
+            if (_typeNameToDesc.TryGetValue(typeName, out desc))
+            {
+                return desc;
+            }
+
+            var typeId = GetTypeId(typeName, _cfg.IdMapper);
+
+            return GetDescriptor(true, typeId, typeName: typeName);
         }
 
         /// <summary>
@@ -416,18 +416,18 @@ namespace Apache.Ignite.Core.Impl.Binary
         /// </summary>
         /// <param name="userType">User type flag.</param>
         /// <param name="typeId">Type id.</param>
-        /// <param name="requiresType">
-        /// If set to true, resulting descriptor must have Type property populated.
+        /// <param name="requiresType">If set to true, resulting descriptor must have Type property populated.
         /// <para />
         /// When working in binary mode, we don't need Type. And there is no Type at all in some cases.
         /// So we should not attempt to call BinaryProcessor right away.
         /// Only when we really deserialize the value, requiresType is set to true
-        /// and we attempt to resolve the type by all means.
-        /// </param>
+        /// and we attempt to resolve the type by all means.</param>
+        /// <param name="typeName">Known type name.</param>
         /// <returns>
         /// Descriptor.
         /// </returns>
-        public IBinaryTypeDescriptor GetDescriptor(bool userType, int typeId, bool requiresType = false)
+        public IBinaryTypeDescriptor GetDescriptor(bool userType, int typeId, bool requiresType = false, 
+            string typeName = null)
         {
             BinaryFullTypeDescriptor desc;
 
@@ -442,7 +442,7 @@ namespace Apache.Ignite.Core.Impl.Binary
             if (requiresType && _ignite != null)
             {
                 // Check marshaller context for dynamically registered type.
-                var typeName = _ignite.BinaryProcessor.GetTypeName(typeId);
+                typeName = typeName ?? _ignite.BinaryProcessor.GetTypeName(typeId);
 
                 if (typeName != null)
                 {
@@ -460,15 +460,16 @@ namespace Apache.Ignite.Core.Impl.Binary
 
             if (meta != BinaryType.Empty)
             {
-                desc = new BinaryFullTypeDescriptor(null, meta.TypeId, meta.TypeName, true, null, null, null, false,
-                    meta.AffinityKeyFieldName, meta.IsEnum);
-
-                _idToDesc.GetOrAdd(typeKey, _ => desc);
+                var typeCfg = new BinaryTypeConfiguration(meta.TypeName)
+                {
+                    IsEnum = meta.IsEnum,
+                    AffinityKeyFieldName = meta.AffinityKeyFieldName
+                };
 
-                return desc;
+                return AddUserType(typeCfg, new TypeResolver());
             }
 
-            return new BinarySurrogateTypeDescriptor(_cfg, typeId, null);
+            return new BinarySurrogateTypeDescriptor(_cfg, typeId, typeName);
         }
 
         /// <summary>
@@ -507,7 +508,7 @@ namespace Apache.Ignite.Core.Impl.Binary
 
             desc = desc == null
                 ? new BinaryFullTypeDescriptor(type, typeId, typeName, true, _cfg.NameMapper,
-                    _cfg.IdMapper, ser, false, null, type.IsEnum, registered)
+                    _cfg.IdMapper, ser, false, null, BinaryUtils.IsIgniteEnum(type), registered)
                 : new BinaryFullTypeDescriptor(desc, type, ser, registered);
 
             if (RegistrationDisabled)
@@ -540,11 +541,10 @@ namespace Apache.Ignite.Core.Impl.Binary
         /// <summary>
         /// Add user type.
         /// </summary>
-        /// <param name="cfg">The binary configuration.</param>
         /// <param name="typeCfg">Type configuration.</param>
         /// <param name="typeResolver">The type resolver.</param>
         /// <exception cref="BinaryObjectException"></exception>
-        private void AddUserType(BinaryConfiguration cfg, BinaryTypeConfiguration typeCfg, TypeResolver typeResolver)
+        private BinaryFullTypeDescriptor AddUserType(BinaryTypeConfiguration typeCfg, TypeResolver typeResolver)
         {
             // Get converter/mapper/serializer.
             IBinaryNameMapper nameMapper = typeCfg.NameMapper ?? _cfg.NameMapper ?? GetDefaultNameMapper();
@@ -560,23 +560,23 @@ namespace Apache.Ignite.Core.Impl.Binary
             {
                 ValidateUserType(type);
 
-                if (typeCfg.IsEnum != type.IsEnum)
+                if (typeCfg.IsEnum != BinaryUtils.IsIgniteEnum(type))
                 {
                     throw new BinaryObjectException(
                         string.Format(
                             "Invalid IsEnum flag in binary type configuration. " +
-                            "Configuration value: IsEnum={0}, actual type: IsEnum={1}",
-                            typeCfg.IsEnum, type.IsEnum));
+                            "Configuration value: IsEnum={0}, actual type: IsEnum={1}, type={2}",
+                            typeCfg.IsEnum, type.IsEnum, type));
                 }
 
                 // Type is found.
                 var typeName = GetTypeName(type, nameMapper);
                 int typeId = GetTypeId(typeName, idMapper);
                 var affKeyFld = typeCfg.AffinityKeyFieldName ?? GetAffinityKeyFieldNameFromAttribute(type);
-                var serializer = GetSerializer(cfg, typeCfg, type, typeId, nameMapper, idMapper, _log);
+                var serializer = GetSerializer(_cfg, typeCfg, type, typeId, nameMapper, idMapper, _log);
 
-                AddType(type, typeId, typeName, true, keepDeserialized, nameMapper, idMapper, serializer,
-                    affKeyFld, type.IsEnum);
+                return AddType(type, typeId, typeName, true, keepDeserialized, nameMapper, idMapper, serializer,
+                    affKeyFld, BinaryUtils.IsIgniteEnum(type));
             }
             else
             {
@@ -585,7 +585,7 @@ namespace Apache.Ignite.Core.Impl.Binary
 
                 int typeId = GetTypeId(typeName, idMapper);
 
-                AddType(null, typeId, typeName, true, keepDeserialized, nameMapper, idMapper, null,
+                return AddType(null, typeId, typeName, true, keepDeserialized, nameMapper, idMapper, null,
                     typeCfg.AffinityKeyFieldName, typeCfg.IsEnum);
             }
         }
@@ -653,7 +653,7 @@ namespace Apache.Ignite.Core.Impl.Binary
         /// <param name="serializer">Serializer.</param>
         /// <param name="affKeyFieldName">Affinity key field name.</param>
         /// <param name="isEnum">Enum flag.</param>
-        private void AddType(Type type, int typeId, string typeName, bool userType,
+        private BinaryFullTypeDescriptor AddType(Type type, int typeId, string typeName, bool userType,
             bool keepDeserialized, IBinaryNameMapper nameMapper, IBinaryIdMapper idMapper,
             IBinarySerializerInternal serializer, string affKeyFieldName, bool isEnum)
         {
@@ -685,6 +685,8 @@ namespace Apache.Ignite.Core.Impl.Binary
                 _typeNameToDesc.GetOrAdd(typeName, x => descriptor);
 
             _idToDesc.GetOrAdd(typeKey, _ => descriptor);
+
+            return descriptor;
         }
 
         /// <summary>

http://git-wip-us.apache.org/repos/asf/ignite/blob/b5c7b6f5/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/Metadata/BinaryType.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/Metadata/BinaryType.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/Metadata/BinaryType.cs
index 837c28a..db54ce7 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/Metadata/BinaryType.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/Metadata/BinaryType.cs
@@ -17,9 +17,11 @@
 
 namespace Apache.Ignite.Core.Impl.Binary.Metadata
 {
+    using System;
     using System.Collections.Generic;
     using System.Diagnostics;
     using System.Diagnostics.CodeAnalysis;
+    using System.Linq;
     using Apache.Ignite.Core.Binary;
     using Apache.Ignite.Core.Impl.Common;
 
@@ -30,7 +32,7 @@ namespace Apache.Ignite.Core.Impl.Binary.Metadata
     {
         /** Empty metadata. */
         public static readonly BinaryType Empty =
-            new BinaryType(BinaryUtils.TypeObject, BinaryTypeNames.TypeNameObject, null, null, false);
+            new BinaryType(BinaryUtils.TypeObject, BinaryTypeNames.TypeNameObject, null, null, false, null, null);
 
         /** Empty dictionary. */
         private static readonly IDictionary<string, BinaryField> EmptyDict = new Dictionary<string, BinaryField>();
@@ -44,6 +46,12 @@ namespace Apache.Ignite.Core.Impl.Binary.Metadata
         /** Fields. */
         private readonly IDictionary<string, BinaryField> _fields;
 
+        /** Enum values. */
+        private readonly IDictionary<string, int> _enumNameToValue;
+
+        /** Enum names. */
+        private readonly IDictionary<int, string> _enumValueToName;
+
         /** Enum flag. */
         private readonly bool _isEnum;
 
@@ -59,6 +67,9 @@ namespace Apache.Ignite.Core.Impl.Binary.Metadata
         /** Type descriptor. */
         private readonly IBinaryTypeDescriptor _descriptor;
 
+        /** Marshaller. */
+        private readonly Marshaller _marshaller;
+
         /// <summary>
         /// Initializes the <see cref="BinaryType"/> class.
         /// </summary>
@@ -117,7 +128,7 @@ namespace Apache.Ignite.Core.Impl.Binary.Metadata
         /// Initializes a new instance of the <see cref="BinaryType" /> class.
         /// </summary>
         /// <param name="reader">The reader.</param>
-        public BinaryType(IBinaryRawReader reader)
+        public BinaryType(BinaryReader reader)
         {
             _typeId = reader.ReadInt();
             _typeName = reader.ReadString();
@@ -136,15 +147,34 @@ namespace Apache.Ignite.Core.Impl.Binary.Metadata
             }
             
             _isEnum = reader.ReadBoolean();
+
+            if (_isEnum)
+            {
+                var count = reader.ReadInt();
+
+                _enumNameToValue = new Dictionary<string, int>(count);
+
+                for (var i = 0; i < count; i++)
+                {
+                    _enumNameToValue[reader.ReadString()] = reader.ReadInt();
+                }
+
+                _enumValueToName = _enumNameToValue.ToDictionary(x => x.Value, x => x.Key);
+            }
+
+            _marshaller = reader.Marshaller;
         }
 
         /// <summary>
-        /// Initializes a new instance of the <see cref="BinaryType"/> class.
+        /// Initializes a new instance of the <see cref="BinaryType" /> class.
         /// </summary>
         /// <param name="desc">Descriptor.</param>
+        /// <param name="marshaller">Marshaller.</param>
         /// <param name="fields">Fields.</param>
-        public BinaryType(IBinaryTypeDescriptor desc, IDictionary<string, BinaryField> fields = null) 
-            : this (desc.TypeId, desc.TypeName, fields, desc.AffinityKeyFieldName, desc.IsEnum)
+        public BinaryType(IBinaryTypeDescriptor desc, Marshaller marshaller, 
+            IDictionary<string, BinaryField> fields = null) 
+            : this (desc.TypeId, desc.TypeName, fields, desc.AffinityKeyFieldName, desc.IsEnum, 
+                  GetEnumValues(desc), marshaller)
         {
             _descriptor = desc;
         }
@@ -157,14 +187,24 @@ namespace Apache.Ignite.Core.Impl.Binary.Metadata
         /// <param name="fields">Fields.</param>
         /// <param name="affKeyFieldName">Affinity key field name.</param>
         /// <param name="isEnum">Enum flag.</param>
+        /// <param name="enumValues">Enum values.</param>
+        /// <param name="marshaller">Marshaller.</param>
         public BinaryType(int typeId, string typeName, IDictionary<string, BinaryField> fields,
-            string affKeyFieldName, bool isEnum)
+            string affKeyFieldName, bool isEnum, IDictionary<string, int> enumValues, Marshaller marshaller)
         {
             _typeId = typeId;
             _typeName = typeName;
             _affinityKeyFieldName = affKeyFieldName;
             _fields = fields;
             _isEnum = isEnum;
+            _enumNameToValue = enumValues;
+
+            if (_enumNameToValue != null)
+            {
+                _enumValueToName = _enumNameToValue.ToDictionary(x => x.Value, x => x.Key);
+            }
+
+            _marshaller = marshaller;
         }
 
         /// <summary>
@@ -232,6 +272,27 @@ namespace Apache.Ignite.Core.Impl.Binary.Metadata
             get { return _isEnum; }
         }
 
+        /** <inheritdoc /> */
+        public IEnumerable<IBinaryObject> GetEnumValues()
+        {
+            if (!_isEnum)
+            {
+                throw new NotSupportedException(
+                    "IBinaryObject.Value is only supported for enums. " +
+                    "Check IBinaryObject.GetBinaryType().IsEnum property before accessing Value.");
+            }
+
+            if (_marshaller == null)
+            {
+                yield break;
+            }
+
+            foreach (var pair in _enumValueToName)
+            {
+                yield return new BinaryEnum(_typeId, pair.Key, _marshaller);
+            }
+        }
+
         /// <summary>
         /// Gets the descriptor.
         /// </summary>
@@ -250,6 +311,14 @@ namespace Apache.Ignite.Core.Impl.Binary.Metadata
         }
 
         /// <summary>
+        /// Gets the enum values map.
+        /// </summary>
+        public IDictionary<string, int> EnumValuesMap
+        {
+            get { return _enumNameToValue; }
+        }
+
+        /// <summary>
         /// Updates the fields.
         /// </summary>
         public void UpdateFields(IDictionary<string, BinaryField> fields)
@@ -262,5 +331,103 @@ namespace Apache.Ignite.Core.Impl.Binary.Metadata
             foreach (var field in fields)
                 _fields[field.Key] = field.Value;
         }
+
+        /// <summary>
+        /// Gets the enum value by name.
+        /// </summary>
+        public int? GetEnumValue(string valueName)
+        {
+            IgniteArgumentCheck.NotNullOrEmpty(valueName, "valueName");
+
+            if (!_isEnum)
+            {
+                throw new NotSupportedException("Can't get enum value for a non-enum type: " + _typeName);
+            }
+
+            int res;
+
+            return _enumNameToValue != null && _enumNameToValue.TryGetValue(valueName, out res) ? res : (int?) null;
+        }
+
+        /// <summary>
+        /// Gets the name of the enum value.
+        /// </summary>
+        public string GetEnumName(int value)
+        {
+            if (!_isEnum)
+            {
+                throw new NotSupportedException("Can't get enum value for a non-enum type: " + _typeName);
+            }
+
+            string res;
+
+            return _enumValueToName != null && _enumValueToName.TryGetValue(value, out res) ? res : null;
+        }
+
+        /// <summary>
+        /// Gets the enum values.
+        /// </summary>
+        private static IDictionary<string, int> GetEnumValues(IBinaryTypeDescriptor desc)
+        {
+            if (desc == null || desc.Type == null || !desc.IsEnum)
+            {
+                return null;
+            }
+
+            var enumType = desc.Type;
+
+            var values = Enum.GetValues(enumType);
+            var res = new Dictionary<string, int>(values.Length);
+
+            var underlyingType = Enum.GetUnderlyingType(enumType);
+
+            foreach (var value in values)
+            {
+                var name = Enum.GetName(enumType, value);
+                Debug.Assert(name != null);
+
+                res[name] = GetEnumValueAsInt(underlyingType, value);
+            }
+
+            return res;
+        }
+
+        /// <summary>
+        /// Gets the enum value as int.
+        /// </summary>
+        private static int GetEnumValueAsInt(Type underlyingType, object value)
+        {
+            if (underlyingType == typeof(int))
+            {
+                return (int) value;
+            }
+
+            if (underlyingType == typeof(byte))
+            {
+                return (byte) value;
+            }
+
+            if (underlyingType == typeof(sbyte))
+            {
+                return (sbyte) value;
+            }
+
+            if (underlyingType == typeof(short))
+            {
+                return (short) value;
+            }
+
+            if (underlyingType == typeof(ushort))
+            {
+                return (ushort) value;
+            }
+
+            if (underlyingType == typeof(uint))
+            {
+                return unchecked((int) (uint) value);
+            }
+
+            throw new BinaryObjectException("Unexpected enum underlying type: " + underlyingType);
+        }
     }
 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/b5c7b6f5/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/Metadata/BinaryTypeHolder.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/Metadata/BinaryTypeHolder.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/Metadata/BinaryTypeHolder.cs
index cdbc687..7e1e970 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/Metadata/BinaryTypeHolder.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/Metadata/BinaryTypeHolder.cs
@@ -17,8 +17,8 @@
 
 namespace Apache.Ignite.Core.Impl.Binary.Metadata
 {
-    using System;
     using System.Collections.Generic;
+    using System.Diagnostics;
 
     /// <summary>
     /// Metadata for particular type.
@@ -37,6 +37,9 @@ namespace Apache.Ignite.Core.Impl.Binary.Metadata
         /** Enum flag. */
         private readonly bool _isEnum;
 
+        /** Marshaller. */
+        private readonly Marshaller _marshaller;
+
         /** Collection of know field IDs. */
         private volatile HashSet<int> _ids;
 
@@ -46,7 +49,6 @@ namespace Apache.Ignite.Core.Impl.Binary.Metadata
         /** Saved flag (set if type metadata was saved at least once). */
         private volatile bool _saved;
 
-
         /// <summary>
         /// Constructor.
         /// </summary>
@@ -54,12 +56,15 @@ namespace Apache.Ignite.Core.Impl.Binary.Metadata
         /// <param name="typeName">Type name.</param>
         /// <param name="affKeyFieldName">Affinity key field name.</param>
         /// <param name="isEnum">Enum flag.</param>
-        public BinaryTypeHolder(int typeId, string typeName, string affKeyFieldName, bool isEnum)
+        /// <param name="marshaller">The marshaller.</param>
+        public BinaryTypeHolder(int typeId, string typeName, string affKeyFieldName, bool isEnum,
+            Marshaller marshaller)
         {
             _typeId = typeId;
             _typeName = typeName;
             _affKeyFieldName = affKeyFieldName;
             _isEnum = isEnum;
+            _marshaller = marshaller;
         }
 
         /// <summary>
@@ -100,13 +105,19 @@ namespace Apache.Ignite.Core.Impl.Binary.Metadata
         /// <summary>
         /// Merge newly sent field metadatas into existing ones.
         /// </summary>
-        /// <param name="newMap">New field metadatas map.</param>
-        public void Merge(IDictionary<int, Tuple<string, BinaryField>> newMap)
+        /// <param name="meta">Binary type to merge.</param>
+        public void Merge(BinaryType meta)
         {
+            Debug.Assert(meta != null);
+            
             _saved = true;
 
-            if (newMap == null || newMap.Count == 0)
+            var fieldsMap = meta.GetFieldsMap();
+
+            if (fieldsMap.Count == 0)
+            {
                 return;
+            }
 
             lock (this)
             {
@@ -118,20 +129,27 @@ namespace Apache.Ignite.Core.Impl.Binary.Metadata
 
                 IDictionary<string, BinaryField> newFields = meta0 != null 
                     ? new Dictionary<string, BinaryField>(meta0.GetFieldsMap()) 
-                    : new Dictionary<string, BinaryField>(newMap.Count);
+                    : new Dictionary<string, BinaryField>(fieldsMap.Count);
 
                 // 2. Add new fields.
-                foreach (var newEntry in newMap)
+                foreach (var fieldMeta in fieldsMap)
                 {
-                    if (!newIds.Contains(newEntry.Key))
-                        newIds.Add(newEntry.Key);
+                    int fieldId = BinaryUtils.FieldId(meta.TypeId, fieldMeta.Key, null, null);
 
-                    if (!newFields.ContainsKey(newEntry.Value.Item1))
-                        newFields[newEntry.Value.Item1] = newEntry.Value.Item2;
+                    if (!newIds.Contains(fieldId))
+                    {
+                        newIds.Add(fieldId);
+                    }
+
+                    if (!newFields.ContainsKey(fieldMeta.Key))
+                    {
+                        newFields[fieldMeta.Key] = fieldMeta.Value;
+                    }
                 }
 
                 // 3. Assign new meta. Order is important here: meta must be assigned before field IDs.
-                _meta = new BinaryType(_typeId, _typeName, newFields, _affKeyFieldName, _isEnum);
+                _meta = new BinaryType(_typeId, _typeName, newFields, _affKeyFieldName, _isEnum, 
+                    meta.EnumValuesMap, _marshaller);
                 _ids = newIds;
             }
         }