OrdinalMap[] EmitOrdinals(ILGenerator il, MappingResult result)
        {
            ValueMap[]   fields           = result.ValueMappings;
            OrdinalMap[] ordinals_mapping = new OrdinalMap[fields.Length];

            if (fields.Length > 0)
            {
                MethodInfo get_ordinal_method =
                    Dynamics_.GetDataReaderMethod("GetOrdinal");

                il.Emit(OpCodes.Ldarg_0);
                il.Emit(OpCodes.Ldc_I4, fields.Length);
                il.Emit(OpCodes.Newarr, typeof(int));
                il.Emit(OpCodes.Stfld, result.OrdinalsField);

                for (int i = 0, j = fields.Length; i < j; i++)
                {
                    il.Emit(OpCodes.Ldarg_0);
                    il.Emit(OpCodes.Ldfld, result.OrdinalsField);
                    il.Emit(OpCodes.Ldc_I4, i);
                    il.Emit(OpCodes.Ldarg_1);
                    il.Emit(OpCodes.Ldstr, fields[i].Key);
                    il.Emit(OpCodes.Callvirt, get_ordinal_method);
                    il.Emit(OpCodes.Stelem_I4);

                    ordinals_mapping[i] =
                        new OrdinalMap(i, fields[i].Value, fields[i].RawType)
                    {
                        Conversor = fields[i].Conversor
                    };
                }
            }
            return(ordinals_mapping);
        }
        /// <summary>
        /// Gets the dynamic type for <typeparamref name="T"/>.
        /// </summary>
        /// <param name="type">
        /// When this method returns contains the type that was dynamically
        /// created for the type <typeparamref name="T"/>, or <c>null</c> is
        /// a dynamic type for <typeparamref name="T"/> does not exists.
        /// </param>
        /// <returns></returns>
        static bool TryGetDynamicType(string prefix, out Type type)
        {
            string dynamic_type_name = Dynamics_.GetDynamicTypeName(prefix,
                                                                    typeof(T));

            type = Dynamics_.ModuleBuilder.GetType(dynamic_type_name);
            return(type != null);
        }
        /// <summary>
        /// Gets the dynamic type for <typeparamref source="T"/>.
        /// </summary>
        /// <returns>
        /// The dynamic type for <typeparamref source="T"/>.
        /// </returns>
        /// <remarks>
        /// If the dynamic type does not already exists, it will be created.
        /// </remarks>
        Type GetDynamicType(string prefix)
        {
            string dynamic_type_name =
                Dynamics_
                .GetDynamicTypeName(prefix, type_t_, "_mapper");
            Type type = Dynamics_.ModuleBuilder.GetType(dynamic_type_name);

            if (type == null)
            {
                // If the specified type is an interface and the factory was not
                // specified we are not able to perform the mapping.
                //
                // TODO(neylor.silva) Create
                if (type_t_.IsInterface && factory_ == null)
                {
                    throw new ArgumentException(
                              R.Mappers_CannotMapInterfaces.Fmt(type_t_.FullName));
                }
                type = MakeDynamicType(dynamic_type_name);
            }
            return(type);
        }
        void EmitMapMethod(TypeBuilder type, MappingResult result)
        {
            MethodBuilder builder = type
                                    .DefineMethod("MapInternal",
                                                  MethodAttributes.Public | MethodAttributes.HideBySig |
                                                  MethodAttributes.Virtual, typeof(T),
                                                  new Type[] { typeof(IDataReader) });

            // define that the method is allowed to acess non-public members.

            /*Type permission = typeof(ReflectionPermissionAttribute);
             * ConstructorInfo ctor =
             * permission
             *  .GetConstructor(new[] { typeof(SecurityAction) });
             * PropertyInfo access = permission.GetProperty("Flags");
             * var reflection_permission_attribute =
             * new CustomAttributeBuilder(ctor, new object[] { SecurityAction.Demand },
             *  new[] { access },
             *  new object[] {
             *    ReflectionPermissionFlag.MemberAccess |
             *      ReflectionPermissionFlag.RestrictedMemberAccess
             *  });
             *
             * builder.SetCustomAttribute(reflection_permission_attribute);*/
            ILGenerator il = builder.GetILGenerator();

            // Create a new instance of the T using the associated class loader and
            // stores in a local variable.
            il.DeclareLocal(type_t_);
            MethodInfo callable = typeof(CallableDelegate <T>).GetMethod("Invoke");

            il.Emit(OpCodes.Ldarg_0);
            il.Emit(OpCodes.Ldfld, result.LoaderField);
            il.Emit(OpCodes.Callvirt, callable);
            il.Emit(OpCodes.Stloc_0);

            // Set the value of the properties of the newly created T object.
            OrdinalMap[] fields = result.OrdinalsMapping;
            for (int i = 0, j = fields.Length; i < j; i++)
            {
                OrdinalMap   field    = fields[i];
                int          ordinal  = field.Key;
                PropertyInfo property = field.Value;

                MethodInfo get_x_method =
                    Dynamics_.GetDataReaderMethod(
                        Dynamics_.GetDataReaderMethodName(field.RawType ??
                                                          property.PropertyType), data_reader_type_);

                // Get the set method of the current property. If the property does
                // not have a set method ignores it.
                MethodInfo set_x_property = property.GetSetMethod(true);
                if (set_x_property == null)
                {
                    throw new ArgumentException(
                              "The property {0} does not have a set method.".Fmt(property.Name));
                }

                // loaded the "data transfer object"
                il.Emit(OpCodes.Ldloc_0);

                // if the conversor method is defined we need to load the
                // "this" pointer onto the stack before the data reader, so we can
                // chain the conversion method call after the value is retrieved
                // from the data reader.
                MethodInfo conversor = null;
                if (field.Conversor != null)
                {
                    conversor = (field.Conversor.Body as MethodCallExpression).Method;
                    if (!conversor.IsStatic || !conversor.IsPublic)
                    {
                        throw new ArgumentException(
                                  "The \"conversor\" method of the property {0} is not static or public"
                                  .Fmt(property.Name));
                    }
                }

                // loads the data reader
                il.Emit(OpCodes.Ldarg_1);

                // load the ordinals_ array
                il.Emit(OpCodes.Ldarg_0);
                il.Emit(OpCodes.Ldfld, result.OrdinalsField);

                // load the element of the array at |ordinal| position
                EmitLoad(il, ordinal);
                il.Emit(OpCodes.Ldelem_I4);

                // call the "get...(int i)" method of the datareader
                //   -> i will be equals to the element loaded from the
                //      array at positiom "ordinal"
                il.Emit(OpCodes.Callvirt, get_x_method);

                // the stack now contains the returned value of "get...(int i)"
                // method.

                // convert the result of get method and...
                if (conversor != null)
                {
                    il.Emit(OpCodes.Call, conversor);
                }

                // store it on the loaded field.
                il.Emit(OpCodes.Callvirt, set_x_property);
            }

            ConstantMap[] constant_maps = result.ConstantMappings;
            for (int i = 0, j = constant_maps.Length; i < j; i++)
            {
                ITypeMap     map      = constant_maps[i].Key;
                PropertyInfo property = constant_maps[i].Value;
                if (map.MapType != TypeMapType.Ignore)
                {
                    // Get the set method of the current property. If the property does
                    // not have a set method ignores it.
                    MethodInfo set_x_property = property.GetSetMethod(true);
                    if (set_x_property == null)
                    {
                        continue;
                    }

                    il.Emit(OpCodes.Ldloc_0);
                    EmitLoad(il, map);
                    il.Emit(OpCodes.Callvirt, set_x_property);
                }
            }

            // load the local T and return.
            il.Emit(OpCodes.Ldloc_0);
            il.Emit(OpCodes.Ret);
        }