You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by ag...@apache.org on 2017/04/18 13:46:21 UTC

[36/62] [abbrv] ignite git commit: IGNITE-2398 .NET: Change default name mapper behavior to full name

http://git-wip-us.apache.org/repos/asf/ignite/blob/3e3b91a8/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinarySurrogateTypeDescriptor.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinarySurrogateTypeDescriptor.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinarySurrogateTypeDescriptor.cs
index cd3becf..737c7c4 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinarySurrogateTypeDescriptor.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinarySurrogateTypeDescriptor.cs
@@ -1,4 +1,4 @@
-/*
+\ufeff/*
  * 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.
@@ -62,19 +62,6 @@ namespace Apache.Ignite.Core.Impl.Binary
             _name = typeName;
         }
 
-        /// <summary>
-        /// Constructor.
-        /// </summary>
-        /// <param name="cfg">Configuration.</param>
-        /// <param name="name">Type name.</param>
-        public BinarySurrogateTypeDescriptor(BinaryConfiguration cfg, string name)
-        {
-            _cfg = cfg;
-            _name = name;
-
-            _id = BinaryUtils.TypeId(name, cfg.NameMapper, cfg.IdMapper);
-        }
-
         /** <inheritDoc /> */
         public Type Type
         {

http://git-wip-us.apache.org/repos/asf/ignite/blob/3e3b91a8/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 ca2c9ae..0979ea5 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryUtils.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryUtils.cs
@@ -22,9 +22,7 @@ namespace Apache.Ignite.Core.Impl.Binary
     using System.Collections.Generic;
     using System.Diagnostics;
     using System.Diagnostics.CodeAnalysis;
-    using System.Globalization;
     using System.IO;
-    using System.Linq;
     using System.Reflection;
     using System.Runtime.InteropServices;
     using System.Text;
@@ -1638,34 +1636,6 @@ namespace Apache.Ignite.Core.Impl.Binary
         }
 
         /**
-         * <summary>Convert type name.</summary>
-         * <param name="typeName">Type name.</param>
-         * <param name="converter">Converter.</param>
-         * <returns>Converted name.</returns>
-         */
-        public static string ConvertTypeName(string typeName, IBinaryNameMapper converter)
-        {
-            var typeName0 = typeName;
-
-            try
-            {
-                if (converter != null)
-                    typeName = converter.GetTypeName(typeName);
-            }
-            catch (Exception e)
-            {
-                throw new BinaryObjectException("Failed to convert type name due to converter exception " +
-                    "[typeName=" + typeName + ", converter=" + converter + ']', e);
-            }
-
-            if (typeName == null)
-                throw new BinaryObjectException("Name converter returned null name for type [typeName=" +
-                    typeName0 + ", converter=" + converter + "]");
-
-            return typeName;
-        }
-
-        /**
          * <summary>Convert field name.</summary>
          * <param name="fieldName">Field name.</param>
          * <param name="converter">Converter.</param>
@@ -1693,67 +1663,13 @@ namespace Apache.Ignite.Core.Impl.Binary
             return fieldName;
         }
 
-        /**
-         * <summary>Extract simple type name.</summary>
-         * <param name="typeName">Type name.</param>
-         * <returns>Simple type name.</returns>
-         */
-        public static string SimpleTypeName(string typeName)
-        {
-            int idx = typeName.LastIndexOf('.');
-
-            return idx < 0 ? typeName : typeName.Substring(idx + 1);
-        }
-
-        /**
-         * <summary>Resolve type ID.</summary>
-         * <param name="typeName">Type name.</param>
-         * <param name="nameMapper">Name mapper.</param>
-         * <param name="idMapper">ID mapper.</param>
-         */
-        public static int TypeId(string typeName, IBinaryNameMapper nameMapper,
-            IBinaryIdMapper idMapper)
-        {
-            Debug.Assert(typeName != null);
-
-            typeName = ConvertTypeName(typeName, nameMapper);
-
-            int id = 0;
-
-            if (idMapper != null)
-            {
-                try
-                {
-                    id = idMapper.GetTypeId(typeName);
-                }
-                catch (Exception e)
-                {
-                    throw new BinaryObjectException("Failed to resolve type ID due to ID mapper exception " +
-                        "[typeName=" + typeName + ", idMapper=" + idMapper + ']', e);
-                }
-            }
-
-            if (id == 0)
-                id = GetStringHashCode(typeName);
-
-            return id;
-        }
-
         /// <summary>
-        /// Gets the name of the type.
+        /// Gets the SQL name of the type.
         /// </summary>
-        /// <param name="type">The type.</param>
-        /// <returns>
-        /// Simple type name for non-generic types; simple type name with appended generic arguments for generic types.
-        /// </returns>
-        public static string GetTypeName(Type type)
+        public static string GetSqlTypeName(Type type)
         {
-            if (!type.IsGenericType)
-                return type.Name;
-
-            var args = type.GetGenericArguments().Select(GetTypeName).Aggregate((x, y) => x + "," + y);
-
-            return string.Format(CultureInfo.InvariantCulture, "{0}[{1}]", type.Name, args);
+            // SQL always uses simple type name without namespace, parent class, etc.
+            return type.FullName;
         }
 
         /**
@@ -1796,31 +1712,6 @@ namespace Apache.Ignite.Core.Impl.Binary
         }
 
         /// <summary>
-        /// Compare contents of two byte array chunks.
-        /// </summary>
-        /// <param name="arr1">Array 1.</param>
-        /// <param name="offset1">Offset 1.</param>
-        /// <param name="len1">Length 1.</param>
-        /// <param name="arr2">Array 2.</param>
-        /// <param name="offset2">Offset 2.</param>
-        /// <param name="len2">Length 2.</param>
-        /// <returns>True if array chunks are equal.</returns>
-        public static bool CompareArrays(byte[] arr1, int offset1, int len1, byte[] arr2, int offset2, int len2)
-        {
-            if (len1 == len2)
-            {
-                for (int i = 0; i < len1; i++)
-                {
-                    if (arr1[offset1 + i] != arr2[offset2 + i])
-                        return false;
-                }
-
-                return true;
-            }
-            return false;
-        }
-
-        /// <summary>
         /// Writes invocation result.
         /// </summary>
         /// <param name="writer">Writer.</param>

http://git-wip-us.apache.org/repos/asf/ignite/blob/3e3b91a8/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 b60ced9..4707ce2 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/Marshaller.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/Marshaller.cs
@@ -407,7 +407,8 @@ namespace Apache.Ignite.Core.Impl.Binary
 
             return _typeNameToDesc.TryGetValue(typeName, out desc)
                 ? (IBinaryTypeDescriptor) desc
-                : new BinarySurrogateTypeDescriptor(_cfg, typeName);
+                : new BinarySurrogateTypeDescriptor(_cfg,
+                    GetTypeId(typeName, _cfg.IdMapper), typeName);
         }
 
         /// <summary>
@@ -444,7 +445,7 @@ namespace Apache.Ignite.Core.Impl.Binary
                 var type = _ignite == null ? null : _ignite.BinaryProcessor.GetType(typeId);
 
                 if (type != null)
-                    return AddUserType(type, typeId, BinaryUtils.GetTypeName(type), true, desc);
+                    return AddUserType(type, typeId, GetTypeName(type), true, desc);
             }
 
             var meta = GetBinaryType(typeId);
@@ -471,8 +472,8 @@ namespace Apache.Ignite.Core.Impl.Binary
         {
             Debug.Assert(type != null);
 
-            var typeName = BinaryUtils.GetTypeName(type);
-            var typeId = BinaryUtils.TypeId(typeName, _cfg.NameMapper, _cfg.IdMapper);
+            var typeName = GetTypeName(type);
+            var typeId = GetTypeId(typeName, _cfg.IdMapper);
 
             var registered = _ignite != null && _ignite.BinaryProcessor.RegisterType(typeId, type);
 
@@ -538,7 +539,7 @@ namespace Apache.Ignite.Core.Impl.Binary
         private void AddUserType(BinaryConfiguration cfg, BinaryTypeConfiguration typeCfg, TypeResolver typeResolver)
         {
             // Get converter/mapper/serializer.
-            IBinaryNameMapper nameMapper = typeCfg.NameMapper ?? _cfg.NameMapper;
+            IBinaryNameMapper nameMapper = typeCfg.NameMapper ?? _cfg.NameMapper ?? GetDefaultNameMapper();
 
             IBinaryIdMapper idMapper = typeCfg.IdMapper ?? _cfg.IdMapper;
 
@@ -561,8 +562,8 @@ namespace Apache.Ignite.Core.Impl.Binary
                 }
 
                 // Type is found.
-                var typeName = BinaryUtils.GetTypeName(type);
-                int typeId = BinaryUtils.TypeId(typeName, nameMapper, idMapper);
+                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);
 
@@ -572,9 +573,9 @@ namespace Apache.Ignite.Core.Impl.Binary
             else
             {
                 // Type is not found.
-                string typeName = BinaryUtils.SimpleTypeName(typeCfg.TypeName);
+                string typeName = GetTypeName(typeCfg.TypeName, nameMapper);
 
-                int typeId = BinaryUtils.TypeId(typeName, nameMapper, idMapper);
+                int typeId = GetTypeId(typeName, idMapper);
 
                 AddType(null, typeId, typeName, true, keepDeserialized, nameMapper, idMapper, null,
                     typeCfg.AffinityKeyFieldName, typeCfg.IsEnum);
@@ -689,11 +690,15 @@ namespace Apache.Ignite.Core.Impl.Binary
 
             serializer = serializer ?? new BinarySystemTypeSerializer<T>(ctor);
 
+            // System types always use simple name mapper.
+            var typeName = type.Name;
+
             if (typeId == 0)
-                typeId = BinaryUtils.TypeId(type.Name, null, null);
+            {
+                typeId = BinaryUtils.GetStringHashCode(typeName);
+            }
 
-            AddType(type, typeId, BinaryUtils.GetTypeName(type), false, false, null, null, serializer, affKeyFldName,
-                false);
+            AddType(type, typeId, typeName, false, false, null, null, serializer, affKeyFldName, false);
         }
 
         /// <summary>
@@ -756,5 +761,71 @@ namespace Apache.Ignite.Core.Impl.Binary
                     type.AssemblyQualifiedName);
             }
         }
+
+        /// <summary>
+        /// Gets the name of the type.
+        /// </summary>
+        private string GetTypeName(Type type, IBinaryNameMapper mapper = null)
+        {
+            return GetTypeName(type.AssemblyQualifiedName, mapper);
+        }
+
+        /// <summary>
+        /// Gets the name of the type.
+        /// </summary>
+        private string GetTypeName(string fullTypeName, IBinaryNameMapper mapper = null)
+        {
+            mapper = mapper ?? _cfg.NameMapper ?? GetDefaultNameMapper();
+
+            var typeName = mapper.GetTypeName(fullTypeName);
+
+            if (typeName == null)
+            {
+                throw new BinaryObjectException("IBinaryNameMapper returned null name for type [typeName=" +
+                                                fullTypeName + ", mapper=" + mapper + "]");
+            }
+
+            return typeName;
+        }
+
+        /// <summary>
+        /// Resolve type ID.
+        /// </summary>
+        /// <param name="typeName">Type name.</param>
+        /// <param name="idMapper">ID mapper.</param>
+        private static int GetTypeId(string typeName, IBinaryIdMapper idMapper)
+        {
+            Debug.Assert(typeName != null);
+
+            int id = 0;
+
+            if (idMapper != null)
+            {
+                try
+                {
+                    id = idMapper.GetTypeId(typeName);
+                }
+                catch (Exception e)
+                {
+                    throw new BinaryObjectException("Failed to resolve type ID due to ID mapper exception " +
+                                                    "[typeName=" + typeName + ", idMapper=" + idMapper + ']', e);
+                }
+            }
+
+            if (id == 0)
+            {
+                id = BinaryUtils.GetStringHashCode(typeName);
+            }
+
+            return id;
+        }
+
+        /// <summary>
+        /// Gets the default name mapper.
+        /// </summary>
+        private static IBinaryNameMapper GetDefaultNameMapper()
+        {
+            return BinaryBasicNameMapper.FullNameInstance;
+        }
     }
 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/3e3b91a8/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/TypeNameParser.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/TypeNameParser.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/TypeNameParser.cs
new file mode 100644
index 0000000..527d47c
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/TypeNameParser.cs
@@ -0,0 +1,384 @@
+\ufeff/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+namespace Apache.Ignite.Core.Impl.Binary
+{
+    using System.Collections.Generic;
+    using Apache.Ignite.Core.Common;
+    using Apache.Ignite.Core.Impl.Common;
+
+    /// <summary>
+    /// Parses .NET-style type names and deconstructs them into parts.
+    /// </summary>
+    internal class TypeNameParser
+    {
+        /** */
+        private readonly int _start;
+
+        /** */
+        private readonly string _typeName;
+
+        /** */
+        private int _pos;
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="TypeNameParser" /> class.
+        /// </summary>
+        private TypeNameParser(string typeName, ref int pos)
+        {
+            _typeName = typeName;
+            _start = pos;
+            _pos = _start;
+
+            NameEnd = -1;
+            NameStart = 0;
+            AssemblyStart = -1;
+            AssemblyEnd = -1;
+            ArrayStart = -1;
+
+            Parse();
+
+            pos = _pos;
+        }
+
+        /// <summary>
+        /// Parses the specified type name.
+        /// </summary>
+        public static TypeNameParser Parse(string typeName)
+        {
+            IgniteArgumentCheck.NotNullOrEmpty(typeName, "typeName");
+
+            int pos = 0;
+
+            return new TypeNameParser(typeName, ref pos);
+        }
+
+        /// <summary>
+        /// Gets the name start.
+        /// </summary>
+        public int NameStart { get; private set; }
+
+        /// <summary>
+        /// Gets the name end.
+        /// </summary>
+        public int NameEnd { get; private set; }
+
+        /// <summary>
+        /// Gets the start of the assembly name.
+        /// </summary>
+        public int AssemblyStart { get; private set; }
+
+        /// <summary>
+        /// Gets the start of the assembly name.
+        /// </summary>
+        public int AssemblyEnd { get; private set; }
+
+        /// <summary>
+        /// Gets the start of the array definition.
+        /// </summary>
+        public int ArrayStart { get; private set; }
+
+        /// <summary>
+        /// Gets the start of the array definition.
+        /// </summary>
+        public int ArrayEnd { get; private set; }
+
+        /// <summary>
+        /// Gets the generics.
+        /// </summary>
+        public ICollection<TypeNameParser> Generics { get; private set; }
+
+        /// <summary>
+        /// Gets the type name (without namespace).
+        /// </summary>
+        public string GetName()
+        {
+            if (NameEnd < 0)
+                return null;
+
+            return _typeName.Substring(NameStart, NameEnd - NameStart + 1);
+        }
+
+        /// <summary>
+        /// Gets the full type name (with namespace).
+        /// </summary>
+        public string GetFullName()
+        {
+            if (NameEnd < 0)
+                return null;
+
+            return _typeName.Substring(_start, NameEnd - _start + 1);
+        }
+
+        /// <summary>
+        /// Gets the array part.
+        /// </summary>
+        public string GetArray()
+        {
+            if (ArrayStart < 0)
+                return null;
+
+            return _typeName.Substring(ArrayStart, ArrayEnd - ArrayStart + 1);
+        }
+
+        /// <summary>
+        /// Gets assembly name part.
+        /// </summary>
+        public string GetAssemblyName()
+        {
+            if (AssemblyStart < 0)
+                return null;
+
+            return _typeName.Substring(AssemblyStart, AssemblyEnd - AssemblyStart + 1);
+        }
+
+        /// <summary>
+        /// Parses this instance.
+        /// </summary>
+        private void Parse()
+        {
+            // Example:
+            // System.Collections.Generic.List`1[[System.Int32[], mscorlib, Version=4.0.0.0, Culture=neutral,
+            // PublicKeyToken =b77a5c561934e089]][], mscorlib, Version=4.0.0.0, Culture=neutral,
+            // PublicKeyToken =b77a5c561934e089
+
+            // 1) Namespace+name, ends with '`' or '[' or ','
+            // 2) Generic, starts with '`'
+            // 3) Array, starts with '['
+            // 4) Assembly, starts with ',', ends with EOL or `]`
+
+            ParseTypeName();
+            ParseGeneric();
+            ParseArrayDefinition();
+            ParseAssemblyName();
+        }
+
+        /// <summary>
+        /// Parses the type name with namespace.
+        /// </summary>
+        private void ParseTypeName()
+        {
+            NameStart = _pos;
+
+            while (Shift())
+            {
+                if (Char == '.' || Char == '+')
+                {
+                    NameStart = _pos + 1;
+                }
+
+                if (Char == '`')
+                {
+                    // Non-null ist indicates detected generic type.
+                    Generics = Generics ?? new List<TypeNameParser>();
+                }
+
+                if (Char == '[' || Char == ']' || Char == ',' || Char == ' ')
+                    break;
+            }
+
+            NameEnd = End ? _pos : _pos - 1;
+        }
+
+        /// <summary>
+        /// Parses the generic part.
+        /// </summary>
+        private void ParseGeneric()
+        {
+            // Generics can be nested:
+            // UserQuery+Gen`1+Gen2`1[[System.Int32, mscorlib],[System.String, mscorlib]]
+
+            if (Generics == null)
+            {
+                return;
+            }
+
+            if (Char != '[')
+            {
+                throw new IgniteException("Invalid generic type name, number must be followed by '[': " + _typeName);
+            }
+
+            while (true)
+            {
+                RequireShift();
+
+                if (Char != '[')
+                {
+                    throw new IgniteException("Invalid generic type name, '[' must be followed by '[': " + _typeName);
+                }
+
+                RequireShift();
+
+                Generics.Add(new TypeNameParser(_typeName, ref _pos));
+
+                if (Char != ']')
+                {
+                    throw new IgniteException("Invalid generic type name, no matching ']': " + _typeName);
+                }
+
+                RequireShift();
+
+                if (Char == ']')
+                {
+                    Shift();
+                    return;
+                }
+
+                if (Char != ',')
+                {
+                    throw new IgniteException("Invalid generic type name, expected ',': " + _typeName);
+                }
+            }
+        }
+
+        /// <summary>
+        /// Parses the array definition.
+        /// </summary>
+        private void ParseArrayDefinition()
+        {
+            if (Char != '[')
+                return;
+
+            ArrayStart = _pos;
+
+            var bracket = true;
+
+            RequireShift();
+            
+            while (true)
+            {
+                if (Char == '[')
+                {
+                    if (bracket)
+                    {
+                        throw new IgniteException("Invalid array specification: " + _typeName);
+                    }
+
+                    bracket = true;
+                }
+                else if (Char == ']')
+                {
+                    if (!bracket)
+                    {
+                        throw new IgniteException("Invalid array specification: " + _typeName);
+                    }
+
+                    bracket = false;
+                }
+                else if (Char == ',')
+                {
+                    if (!bracket)
+                        break;
+                }
+                else
+                {
+                    if (bracket)
+                    {
+                        throw new IgniteException("Invalid array specification: " + _typeName);
+                    }
+
+                    break;
+                }
+
+                if (!Shift())
+                    break;
+            }
+
+            ArrayEnd = Char == ']' ? _pos : _pos - 1;
+        }
+
+        /// <summary>
+        /// Parses assembly name part.
+        /// </summary>
+        private void ParseAssemblyName()
+        {
+            if (Char != ',')
+                return;
+
+            RequireShift();
+
+            SkipSpaces();
+
+            AssemblyStart = _pos;
+
+            while (Char != ']' && Shift())
+            {
+                // No-op.
+            }
+
+            AssemblyEnd = End ? _pos : _pos - 1;
+        }
+
+        /// <summary>
+        /// Shifts the position forward.
+        /// </summary>
+        private bool Shift()
+        {
+            if (_pos < _typeName.Length - 1)
+            {
+                _pos++;
+                return true;
+            }
+
+            return false;
+        }
+
+        /// <summary>
+        /// Requires position shift or throws an error.
+        /// </summary>
+        private void RequireShift()
+        {
+            if (!Shift())
+            {
+                throw new IgniteException("Invalid type name - not enough data: " + _typeName);
+            }
+        }
+
+        /// <summary>
+        /// Skips the spaces.
+        /// </summary>
+        private void SkipSpaces()
+        {
+            while (Char == ' ' && Shift())
+            {
+                // No-op.
+            }
+        }
+
+        /// <summary>
+        /// Gets a value indicating whether we are at the end of the string.
+        /// </summary>
+        private bool End
+        {
+            get { return _pos >= _typeName.Length - 1; }
+        }
+
+        /// <summary>
+        /// Gets the current character.
+        /// </summary>
+        private char Char
+        {
+            get { return _typeName[_pos]; }
+        }
+
+        /** <inheritdoc /> */
+        public override string ToString()
+        {
+            return _typeName;
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/3e3b91a8/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/TypeResolver.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/TypeResolver.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/TypeResolver.cs
index 36dde4b..68222d4 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/TypeResolver.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/TypeResolver.cs
@@ -21,20 +21,14 @@ namespace Apache.Ignite.Core.Impl.Binary
     using System.Collections.Generic;
     using System.Diagnostics;
     using System.Diagnostics.CodeAnalysis;
-    using System.Globalization;
     using System.Linq;
     using System.Reflection;
-    using System.Text.RegularExpressions;
 
     /// <summary>
     /// Resolves types by name.
     /// </summary>
     internal class TypeResolver
     {
-        /** Regex to parse generic types from binary configuration. Allows nested generics in type arguments. */
-        private static readonly Regex GenericTypeRegex =
-            new Regex(@"([^`,\[\]]*)(?:`[0-9]+)?(?:\[((?:(?<br>\[)|(?<-br>\])|[^\[\]]*)+)\])?", RegexOptions.Compiled);
-
         /** Assemblies loaded in ReflectionOnly mode. */
         private readonly Dictionary<string, Assembly> _reflectionOnlyAssemblies = new Dictionary<string, Assembly>();
 
@@ -54,11 +48,15 @@ namespace Apache.Ignite.Core.Impl.Binary
             var type = Type.GetType(typeName, false);
 
             if (type != null)
+            {
                 return type;
+            }
+
+            var parsedType = TypeNameParser.Parse(typeName);
 
             // Partial names should be resolved by scanning assemblies.
-            return ResolveType(assemblyName, typeName, AppDomain.CurrentDomain.GetAssemblies())
-                ?? ResolveTypeInReferencedAssemblies(assemblyName, typeName);
+            return ResolveType(assemblyName, parsedType, AppDomain.CurrentDomain.GetAssemblies())
+                ?? ResolveTypeInReferencedAssemblies(assemblyName, parsedType);
         }
 
         /// <summary>
@@ -70,10 +68,23 @@ namespace Apache.Ignite.Core.Impl.Binary
         /// <returns> 
         /// Resolved type. 
         /// </returns>
-        private static Type ResolveType(string assemblyName, string typeName, ICollection<Assembly> assemblies)
+        private static Type ResolveType(string assemblyName, TypeNameParser typeName, ICollection<Assembly> assemblies)
         {
-            return ResolveGenericType(assemblyName, typeName, assemblies) ??
-                   ResolveNonGenericType(assemblyName, typeName, assemblies);
+            var type = ResolveNonGenericType(assemblyName, typeName.GetFullName(), assemblies);
+
+            if (type == null)
+            {
+                return null;
+            }
+
+            if (type.IsGenericTypeDefinition && typeName.Generics != null)
+            {
+                var genArgs = typeName.Generics.Select(x => ResolveType(assemblyName, x, assemblies)).ToArray();
+
+                return type.MakeGenericType(genArgs);
+            }
+
+            return type;
         }
 
         /// <summary>
@@ -85,64 +96,34 @@ namespace Apache.Ignite.Core.Impl.Binary
         /// <returns>Resolved type, or null.</returns>
         private static Type ResolveNonGenericType(string assemblyName, string typeName, ICollection<Assembly> assemblies)
         {
+            // Fully-qualified name can be resolved with system mechanism.
+            var type = Type.GetType(typeName, false);
+
+            if (type != null)
+            {
+                return type;
+            }
+
             if (!string.IsNullOrEmpty(assemblyName))
+            {
                 assemblies = assemblies
                     .Where(x => x.FullName == assemblyName || x.GetName().Name == assemblyName).ToArray();
+            }
 
             if (!assemblies.Any())
+            {
                 return null;
+            }
 
             // Trim assembly qualification
             var commaIdx = typeName.IndexOf(',');
 
             if (commaIdx > 0)
+            {
                 typeName = typeName.Substring(0, commaIdx);
+            }
 
-            return assemblies.Select(a => a.GetType(typeName, false, false)).FirstOrDefault(type => type != null);
-        }
-
-        /// <summary>
-        /// Resolves the name of the generic type by resolving each generic arg separately 
-        /// and substituting it's fully qualified name.
-        /// (Assembly.GetType finds generic types only when arguments are fully qualified).
-        /// </summary>
-        /// <param name="assemblyName">Name of the assembly.</param>
-        /// <param name="typeName">Name of the type.</param>
-        /// <param name="assemblies">Assemblies</param>
-        /// <returns>Fully qualified generic type name, or null if argument(s) could not be resolved.</returns>
-        private static Type ResolveGenericType(string assemblyName, string typeName, ICollection<Assembly> assemblies)
-        {
-            var match = GenericTypeRegex.Match(typeName);
-
-            if (!match.Success || !match.Groups[2].Success)
-                return null;
-
-            // Try to construct generic type; each generic arg can also be a generic type.
-            var genericArgs = GenericTypeRegex.Matches(match.Groups[2].Value)
-                .OfType<Match>().Select(m => m.Value).Where(v => !string.IsNullOrWhiteSpace(v))
-                .Select(v => ResolveType(null, TrimBrackets(v), assemblies)).ToArray();
-
-            if (genericArgs.Any(x => x == null))
-                return null;
-
-            var genericType = ResolveNonGenericType(assemblyName,
-                string.Format(CultureInfo.InvariantCulture, "{0}`{1}", match.Groups[1].Value, genericArgs.Length),
-                assemblies);
-
-            if (genericType == null)
-                return null;
-
-            return genericType.MakeGenericType(genericArgs);
-        }
-
-        /// <summary>
-        /// Trims the brackets from generic type arg.
-        /// </summary>
-        private static string TrimBrackets(string s)
-        {
-            return s.StartsWith("[", StringComparison.Ordinal) && s.EndsWith("]", StringComparison.Ordinal) 
-                ? s.Substring(1, s.Length - 2) 
-                : s;
+            return assemblies.Select(a => a.GetType(typeName, false, false)).FirstOrDefault(x => x != null);
         }
 
         /// <summary>
@@ -153,7 +134,7 @@ namespace Apache.Ignite.Core.Impl.Binary
         /// <returns>
         /// Resolved type.
         /// </returns>
-        private Type ResolveTypeInReferencedAssemblies(string assemblyName, string typeName)
+        private Type ResolveTypeInReferencedAssemblies(string assemblyName, TypeNameParser typeName)
         {
             ResolveEventHandler resolver = (sender, args) => GetReflectionOnlyAssembly(args.Name);
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/3e3b91a8/modules/platforms/dotnet/Apache.Ignite.Linq/Impl/CacheFieldsQueryProvider.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Linq/Impl/CacheFieldsQueryProvider.cs b/modules/platforms/dotnet/Apache.Ignite.Linq/Impl/CacheFieldsQueryProvider.cs
index e909575..c665fe7 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Linq/Impl/CacheFieldsQueryProvider.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Linq/Impl/CacheFieldsQueryProvider.cs
@@ -168,7 +168,7 @@ namespace Apache.Ignite.Linq.Impl
         /// </summary>
         private void ValidateTableName()
         {
-            var validTableNames = GetValidTableNames();
+            var validTableNames = GetValidTableNames().Select(x => EscapeTableName(x)).ToArray();
 
             if (!validTableNames.Contains(_tableName, StringComparer.OrdinalIgnoreCase))
             {
@@ -201,7 +201,7 @@ namespace Apache.Ignite.Linq.Impl
         /// </summary>
         private static string GetTableName(QueryEntity e)
         {
-            return e.TableName ?? e.ValueTypeName.Split('.').Last();
+            return e.TableName ?? e.ValueTypeName;
         }
 
         /// <summary>
@@ -213,12 +213,16 @@ namespace Apache.Ignite.Linq.Impl
             var validTableNames = GetValidTableNames();
 
             if (validTableNames.Length == 1)
-                return validTableNames[0];
+            {
+                return EscapeTableName(validTableNames[0]);
+            }
 
-            var valueTypeName = cacheValueType.Name;
+            var valueTypeName = cacheValueType.FullName;
 
             if (validTableNames.Contains(valueTypeName, StringComparer.OrdinalIgnoreCase))
-                return valueTypeName;
+            {
+                return EscapeTableName(valueTypeName);
+            }
 
             throw new CacheException(string.Format("Table name cannot be inferred for cache '{0}', " +
                                                    "please use AsCacheQueryable overload with tableName parameter. " +
@@ -227,6 +231,16 @@ namespace Apache.Ignite.Linq.Impl
         }
 
         /// <summary>
+        /// Escapes the name of the table: strips namespace and nested class qualifiers.
+        /// </summary>
+        private static string EscapeTableName(string valueTypeName)
+        {
+            var nsIndex = Math.Max(valueTypeName.LastIndexOf('.'), valueTypeName.LastIndexOf('+'));
+
+            return nsIndex > 0 ? valueTypeName.Substring(nsIndex + 1) : valueTypeName;
+        }
+
+        /// <summary>
         /// Gets the item type of closed generic i enumerable.
         /// </summary>
         private static Type GetItemTypeOfClosedGenericIEnumerable(Type enumerableType, string argumentName)

http://git-wip-us.apache.org/repos/asf/ignite/blob/3e3b91a8/modules/platforms/dotnet/Apache.Ignite.Linq/Impl/CacheQueryExpressionVisitor.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Linq/Impl/CacheQueryExpressionVisitor.cs b/modules/platforms/dotnet/Apache.Ignite.Linq/Impl/CacheQueryExpressionVisitor.cs
index 99712e3..3659158 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Linq/Impl/CacheQueryExpressionVisitor.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Linq/Impl/CacheQueryExpressionVisitor.cs
@@ -338,8 +338,8 @@ namespace Apache.Ignite.Linq.Impl
 
             var entity = cacheCfg.QueryEntities.FirstOrDefault(e =>
                 e.Aliases != null &&
-                (e.KeyType == keyValTypes[0] || e.KeyTypeName == keyValTypes[0].Name) &&
-                (e.ValueType == keyValTypes[1] || e.ValueTypeName == keyValTypes[1].Name));
+                (e.KeyType == keyValTypes[0] || e.KeyTypeName == keyValTypes[0].FullName) &&
+                (e.ValueType == keyValTypes[1] || e.ValueTypeName == keyValTypes[1].FullName));
 
             if (entity == null)
                 return fieldName;