static Delegate CreateMapFunc(Type typeT, IReadOnlyCollection <Column> columns)
        {
            Contract.Requires(columns != null);
            Contract.Requires(typeT != null);
            Contract.Ensures(Contract.Result <Delegate>() != null);

            if (typeT.IsPrimitiveOrEnum() || typeT.IsNullable() ||
                typeT == typeof(string) || typeT == typeof(Guid) || typeT == typeof(DateTime) || typeT == typeof(DateTimeOffset) ||
                (typeT.IsClass == false && typeT.Name.Contains("Id")) && typeT.Namespace.Contains("BusterWood"))    // special case for Id, IntId, LongId and GuidId structs
            {
                return(CreatePrimativeMapFunc(typeT, columns));
            }

            MappingResult <Thing, Thing> result = Mapping.CreateFromSource(columns.Cast <Thing>().ToList(), Types.WriteablePublicThings(typeT), typeT.Name);

            if (result.Mapped.Count == 0)
            {
                throw new InvalidOperationException("No columns were mapped to type " + typeT);
            }
            var readerParam = Expression.Parameter(typeof(DbDataReader), "reader");
            var resultParam = Expression.Parameter(typeT, "result");
            var block       = CreateMapBlock(typeT, result.Mapped, readerParam, resultParam);
            var func        = typeof(Func <,>).MakeGenericType(new[] { typeof(DbDataReader), typeT });

            return(Expression.Lambda(func, block, new[] { readerParam }).Compile());
        }