private TableDescription GetTableDescription(Type type)
        {
            var tableDescription = new TableDescription();
            object[] tableAtt = type.GetCustomAttributes(typeof (TableNameAttribute), true);

            if (tableAtt.Length > 0)
            {
                var tna = (TableNameAttribute) tableAtt[0];

                tableDescription.Database = tna.Database;
                tableDescription.Owner = tna.Owner;
                tableDescription.TableName = tna.Name;
            }

            return tableDescription;
        }
        private IMapper GetObjectMapper(IObjectMapper mapper, ref int startIndex, TypeAccessor akTypeAccessor)
        {
            //Todo: Remove this Call!
            _extension = TypeExtension.GetTypeExtension(mapper.PropertyType /*_typeAccessor.OriginalType*/, MappingSchema.Extensions);

            Type mapperType    = mapper.PropertyType;
            var  objectMappers = new List <IObjectMapper>();

            TableDescription tableDescription = GetTableDescription(mapperType);

            lock (SetterHandlersLock)
            {
                if (!SettersHandlers.ContainsKey(mapperType))
                {
                    SettersHandlers.Add(mapperType, new Dictionary <string, SetHandler>());
                }

                if (!GettersHandlers.ContainsKey(mapperType))
                {
                    GettersHandlers.Add(mapperType, new Dictionary <string, GetHandler>());
                }
            }

            PropertyInfo[] properties = mapperType.GetProperties();

            MemberAccessor primaryKeyMemberAccessor = null;

            foreach (MemberAccessor ma in akTypeAccessor)
            {
                //  Setters
                lock (SetterHandlersLock)
                {
                    if (!SettersHandlers[mapper.PropertyType].ContainsKey(ma.Name))
                    {
                        SettersHandlers[mapper.PropertyType].Add(ma.Name, ma.SetValue);
                    }
                }

                if (GetPrimaryKey(ma) != null)
                {
                    primaryKeyMemberAccessor = ma;

                    lock (SetterHandlersLock)
                    {
                        if (!GettersHandlers[mapperType].ContainsKey(ma.Name))
                        {
                            GettersHandlers[mapperType].Add(ma.Name, ma.GetValue);
                        }
                    }
                    mapper.PrimaryKeyValueGetters.Add(GettersHandlers[mapperType][ma.Name]);
                    mapper.PrimaryKeyNames.Add(ma.Name);

                    if (mapper.Association != null && (mapper.Association.OtherKey == null || mapper.Association.OtherKey.Length == 0))
                    {
                        mapper.Association.OtherKey = new[] { ma.Name };
                    }
                }
            }
            if (primaryKeyMemberAccessor == null)
            {
                throw new Exception("PrimaryKey attribute not found on type: " + mapperType);
            }

            foreach (PropertyInfo prop in properties)
            {
                var ma = akTypeAccessor.First(x => x.Name == prop.Name);

                // Check if the accessor is an association
                var association = GetAssociation(ma);
                if (association != null)
                {
                    //  Getters for IObjectMapper
                    lock (SetterHandlersLock)
                        if (!GettersHandlers[mapperType].ContainsKey(prop.Name))
                        {
                            GettersHandlers[mapperType].Add(prop.Name, ma.GetValue);
                        }

                    bool          isCollection = prop.PropertyType.GetInterfaces().ToList().Contains(typeof(IList));
                    IObjectMapper propertiesMapping;
                    if (!isCollection)
                    {
                        // TODO Generate this instance using the CreateObjectMapperInstance method of fullMappingSchema
                        // _db.MappingSchema.CreateObjectMapperInstance(prop.PropertyType)

                        propertiesMapping = new FullObjectMapper(_db, _ignoreLazyLoad, _factoryType)
                        {
                            PropertyType = prop.PropertyType,
                            IsNullable   = association.CanBeNull,
                            Getter       = GettersHandlers[mapperType][prop.Name],
                        };
                    }
                    else
                    {
                        Type             listElementType            = GetGenericType(prop.PropertyType);
                        TableDescription colElementTableDescription = GetTableDescription(listElementType);

                        // TODO Generate this instance using the CreateObjectMapperInstance method of fullMappingSchema
                        propertiesMapping = new CollectionFullObjectMapper(_db, _factoryType)
                        {
                            PropertyType           = listElementType,
                            Getter                 = GettersHandlers[mapperType][prop.Name],
                            TableName              = colElementTableDescription.TableName,
                            PropertyCollectionType = prop.PropertyType,
                        };

                        if (mapper is FullObjectMapper)
                        {
                            ((FullObjectMapper)mapper).ColParent = true;
                        }
                    }

                    if (association.ThisKey == null || association.ThisKey.Length == 0)
                    {
                        association.ThisKey = new[] { primaryKeyMemberAccessor.Name }
                    }
                    ;

                    bool isLazy = false;
                    if (!_ignoreLazyLoad)
                    {
                        var lazy = GetLazyInstance(ma); // prop.GetCustomAttributes(typeof(LazyInstanceAttribute), true);
                        if (lazy)
                        {
                            isLazy = true;
                            mapper.ContainsLazyChild = true;

                            //  Getters
                            lock (SetterHandlersLock)
                                if (!GettersHandlers[mapperType].ContainsKey(primaryKeyMemberAccessor.Name))
                                {
                                    GettersHandlers[mapperType].Add(primaryKeyMemberAccessor.Name, primaryKeyMemberAccessor.GetValue);
                                }
                        }
                    }

                    propertiesMapping.Association  = association;
                    propertiesMapping.PropertyName = prop.Name;
                    propertiesMapping.IsLazy       = isLazy;
                    propertiesMapping.Setter       = SettersHandlers[mapperType][prop.Name];

                    if (propertiesMapping.IsLazy)
                    {
                        propertiesMapping.ParentKeyGetter = GettersHandlers[mapperType][primaryKeyMemberAccessor.Name];
                    }
                    objectMappers.Add(propertiesMapping);
                }
                else
                {
                    var mapIgnore = GetMapIgnore(ma);
                    if (mapIgnore)
                    {
                        continue;
                    }

                    var    mapField   = GetMapField(ma);
                    string columnName = mapField != null ? mapField.MapName : prop.Name;

                    var map = new ValueMapper
                    {
                        PropertyName    = prop.Name,
                        PropertyType    = prop.PropertyType,
                        DataReaderIndex = startIndex,
                        Setter          = SettersHandlers[mapperType][prop.Name],
                        TableName       = tableDescription.TableName,
                        ColumnName      = columnName,
                    };

                    var mapColumnName = map.GetColumnName(columnName);
                    map.ColumnAlias = columnName == mapColumnName ? null : mapColumnName;

                    mapper.PropertiesMapping.Add(map);

                    var pkField = GetPrimaryKey(ma);
                    if (pkField != null)
                    {
                        mapper.DataReaderIndex = startIndex;
                    }

                    startIndex++;
                }
            }

            foreach (IObjectMapper objMap in objectMappers)
            {
                #region Check mapping recursion

                IObjectMapper cel = mapper;
                while (cel != null)
                {
                    if (mapper.PropertyType == objMap.PropertyType)
                    {
                        continue;
                    }

                    cel = (IObjectMapper)cel.ParentMapping;
                }

                #endregion

                objMap.ParentMapping = mapper;
                mapper.PropertiesMapping.Add(GetObjectMapper(objMap, ref startIndex, MappingSchema.GetObjectMapper(objMap.PropertyType).TypeAccessor));
            }

            return(mapper);
        }