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); }