Inheritance: IMappingElement
        private static NamespaceMapping CreateNamespace(string ns, IEnumerable<Type> availableTypes, AssemblyMappingConfiguration assembly, IMappingElement parent = null)
        {
            var separator = new[] { TypeSeparator };
            const StringSplitOptions options = StringSplitOptions.RemoveEmptyEntries;

            var @namespace = new NamespaceMapping
                                 {
                                     ID = Guid.NewGuid().ToString("N"),
                                     Name = ns.Split(separator, options).LastOrDefault(),
                                     FullName = ns,
                                     Parent = parent,
                                     Visible = true
                                 };

            @namespace.Types = availableTypes
                .Where(t => t.Namespace == ns)
                .Select(t => CreateTypeMapping(t, @namespace, assembly.For(t)))
                .ToList();

            @namespace.Namespaces = availableTypes
                .Where(t => t.Namespace != null && t.Namespace != ns && t.Namespace.StartsWith(ns))
                .GroupBy(t => t.Namespace)
                .Select(g => g.Key.Replace(ns + TypeSeparator, string.Empty).Split(separator, options).FirstOrDefault())
                .Select(nm => CreateNamespace(string.Concat(ns, TypeSeparator, nm), availableTypes.Where(t => t.Namespace != ns), assembly, @namespace))
                .ToList();

            return @namespace;
        }
        private static TypeMapping CreateTypeMapping(Type type, NamespaceMapping @namespace, TypeMappingConfiguration configuration)
        {
            var mapping = new TypeMapping
            {
                ID = Guid.NewGuid().ToString("N"),
                ModelType = type,
                Namespace = @namespace,
                Configuration = configuration
            };

            var attributes = type.GetCustomAttributes(true);

            var displayName = attributes.OfType<System.ComponentModel.DisplayNameAttribute>().FirstOrDefault();
            mapping.Name = (displayName != null && !string.IsNullOrEmpty(displayName.DisplayName))
                               ? displayName.DisplayName
                               : type.Name;

            var scaffold = attributes.OfType<ScaffoldTableAttribute>().FirstOrDefault();
            mapping.Visible = (scaffold == null || scaffold.Scaffold) && !type.GetCustomAttributes(false).OfType<ScriptOnlyAttribute>().Any();

            var properties = OrderProperties(type, TypeDescriptor.GetProperties(type).OfType<PropertyDescriptor>());

            var ignoredNames = new List<string>
            {
                "Equals",
                "GetHashCode",
                "ToString",
                "GetType",
                "ReferenceEquals"
            };

            foreach (var property in properties)
            {
                ignoredNames.Add("get_" + property.Name);
                ignoredNames.Add("set_" + property.Name);
            }

            mapping.Properties = properties.Where(p => !p.Attributes.OfType<ScriptOnlyAttribute>().Any());
            mapping.Key = properties.FirstOrDefault(p => p.Attributes.OfType<KeyAttribute>().Any());
            mapping.Text = properties.FirstOrDefault(p => p.Attributes.OfType<TextAttribute>().Any());

            var constructors = type.GetConstructors()
                .Where(ctor => ctor.IsPublic && ctor.GetParameters().Any())
                .ToList();

            mapping.Constructors = constructors.Select(m => CreateMethodMapping(mapping, m, constructors.IndexOf(m))).ToList();

            mapping.StaticMethods = type.GetMethods(BindingFlags.FlattenHierarchy | BindingFlags.Public | BindingFlags.Static)
                .Where(m => m.IsStatic && m.IsPublic && !ignoredNames.Any(nm => nm == m.Name))
                .GroupBy(m => m.Name)
                .SelectMany(g => g.Select(m => CreateMethodMapping(mapping, m, g.ToList().IndexOf(m))))
                .ToList();

            mapping.InstanceMethods = type.GetMethods()
                .Where(m => !m.IsStatic && m.IsPublic && !ignoredNames.Any(nm => nm == m.Name))
                .GroupBy(m => m.Name)
                .SelectMany(g => g.Select(m => CreateMethodMapping(mapping, m, g.ToList().IndexOf(m))))
                .ToList();

            var queryAttributes = type.GetCustomAttributes(false).OfType<QueryAttribute>();
            if (queryAttributes.Any())
            {
                mapping.Queries = queryAttributes
                   .OrderBy(q => q.Name)
                   .Select(q => CreateQueryMapping(q, mapping))
                   .ToList();
            }
            else
                mapping.Queries = new[] { new QueryAttribute() }.Select(q => CreateQueryMapping(q, mapping)).ToList();

            return mapping;
        }
        private static TypeMapping CreateTypeMapping(Type type, NamespaceMapping @namespace, TypeMappingConfiguration configuration)
        {
            var mapping = new TypeMapping
            {
                ID            = Guid.NewGuid().ToString("N"),
                ModelType     = type,
                Namespace     = @namespace,
                Configuration = configuration
            };

            var attributes = type.GetCustomAttributes(true);

            var displayName = attributes.OfType <System.ComponentModel.DisplayNameAttribute>().FirstOrDefault();

            mapping.Name = (displayName != null && !string.IsNullOrEmpty(displayName.DisplayName))
                                       ? displayName.DisplayName
                                       : type.Name;

            var scaffold = attributes.OfType <ScaffoldTableAttribute>().FirstOrDefault();

            mapping.Visible = (scaffold == null || scaffold.Scaffold) && !type.GetCustomAttributes(false).OfType <ScriptOnlyAttribute>().Any();

            var properties = OrderProperties(type, TypeDescriptor.GetProperties(type).OfType <PropertyDescriptor>());

            var ignoredNames = new List <string>
            {
                "Equals",
                "GetHashCode",
                "ToString",
                "GetType",
                "ReferenceEquals"
            };

            foreach (var property in properties)
            {
                ignoredNames.Add("get_" + property.Name);
                ignoredNames.Add("set_" + property.Name);
            }

            mapping.Properties = properties.Where(p => !p.Attributes.OfType <ScriptOnlyAttribute>().Any());
            mapping.Key        = properties.FirstOrDefault(p => p.Attributes.OfType <KeyAttribute>().Any());
            mapping.Text       = properties.FirstOrDefault(p => p.Attributes.OfType <TextAttribute>().Any());

            var constructors = type.GetConstructors()
                               .Where(ctor => ctor.IsPublic && ctor.GetParameters().Any())
                               .ToList();

            mapping.Constructors = constructors.Select(m => CreateMethodMapping(mapping, m, constructors.IndexOf(m))).ToList();

            mapping.StaticMethods = type.GetMethods(BindingFlags.FlattenHierarchy | BindingFlags.Public | BindingFlags.Static)
                                    .Where(m => m.IsStatic && m.IsPublic && !ignoredNames.Any(nm => nm == m.Name))
                                    .GroupBy(m => m.Name)
                                    .SelectMany(g => g.Select(m => CreateMethodMapping(mapping, m, g.ToList().IndexOf(m))))
                                    .ToList();

            mapping.InstanceMethods = type.GetMethods()
                                      .Where(m => !m.IsStatic && m.IsPublic && !ignoredNames.Any(nm => nm == m.Name))
                                      .GroupBy(m => m.Name)
                                      .SelectMany(g => g.Select(m => CreateMethodMapping(mapping, m, g.ToList().IndexOf(m))))
                                      .ToList();

            var queryAttributes = type.GetCustomAttributes(false).OfType <QueryAttribute>();

            if (queryAttributes.Any())
            {
                mapping.Queries = queryAttributes
                                  .OrderBy(q => q.Name)
                                  .Select(q => CreateQueryMapping(q, mapping))
                                  .ToList();
            }
            else
            {
                mapping.Queries = new[] { new QueryAttribute() }
            }.Select(q => CreateQueryMapping(q, mapping)).ToList();