private static PropertyMapper GenerateIndexerDelegate(Type indexerType, Type targetType, bool ignoreMappings) { var method = new DynamicMethod("Map_" + indexerType.FullName + "_" + targetType.FullName, null, new[] { typeof(object), typeof(object) }, typeof(Mapper).Module); var il = method.GetILGenerator(); var targetProperties = Reflector.GetPropertyMap(targetType); var entityMap = MappingFactory.GetEntityMap(targetType); var getItem = indexerType.GetMethod("get_Item", new[] { typeof(string) }); var matches = targetProperties.Where(t => t.Value.IsSelectable && t.Key.PropertyType.IsPublic && t.Key.CanWrite && (t.Value.IsSimpleList || t.Value.IsSimpleType || t.Value.IsBinary)); foreach (var match in matches) { var typeConverter = MappingFactory.GetTypeConverter(getItem.ReturnType, match.Key, entityMap); if (match.Value.IsSimpleList && typeConverter == null) { continue; } il.Emit(OpCodes.Ldarg_1); if (typeConverter.Item1 != null) { // New the converter il.Emit(OpCodes.Newobj, typeConverter.Item1.GetConstructor(Type.EmptyTypes)); } il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldstr, MappingFactory.GetPropertyOrColumnName(match.Key, ignoreMappings, entityMap, true)); il.Emit(OpCodes.Callvirt, getItem); if (typeConverter.Item1 == null) { il.EmitCastToReference(match.Key.PropertyType); } else { // Call the convert method il.Emit(OpCodes.Callvirt, typeConverter.Item2.GetMethod("ConvertForward")); } il.EmitCall(OpCodes.Callvirt, match.Key.GetSetMethod(), null); } il.Emit(OpCodes.Ret); var mapper = (PropertyMapper)method.CreateDelegate(typeof(PropertyMapper)); return(mapper); }
private static PropertyMapper GenerateIndexerDelegate(Type indexerType, Type targetType, bool autoTypeCoercion) { var method = new DynamicMethod("Map_" + indexerType.FullName + "_" + targetType.FullName, null, new[] { typeof(object), typeof(object) }, typeof(Mapper).Module); var il = method.GetILGenerator(); var targetProperties = Reflector.GetPropertyMap(targetType); var entityMap = MappingFactory.GetEntityMap(targetType); var getTypeFromHandle = typeof(Type).GetMethod("GetTypeFromHandle"); var getDefaultValue = typeof(System.Activator).GetMethods().FirstOrDefault(m => m.Name == "CreateInstance" && m.GetParameters().Length == 1 && m.GetParameters()[0].ParameterType == typeof(Type)); var useIndexerMethod = true; if (!GetItemMethods.TryGetValue(indexerType, out var getItem) || getItem == null) { getItem = indexerType.GetMethod("get_Item", new[] { typeof(string) }); useIndexerMethod = false; } var matches = targetProperties.Where(t => t.Value.IsSelectable && t.Key.PropertyType.IsPublic && t.Key.CanWrite && (t.Value.IsSimpleList || t.Value.IsSimpleType || t.Value.IsBinary)); foreach (var match in matches) { var typeConverter = MappingFactory.GetTypeConverter(getItem.ReturnType, match.Key, entityMap); if (match.Value.IsSimpleList && typeConverter == null) { continue; } typeConverter = MatchTypeConverter(targetType, match.Value, getItem.ReturnType, typeConverter, autoTypeCoercion); il.Emit(OpCodes.Ldarg_1); if (typeConverter.Item1 != null) { // New the converter il.Emit(OpCodes.Newobj, typeConverter.Item1.GetConstructor(Type.EmptyTypes)); } il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldstr, MappingFactory.GetPropertyOrColumnName(match.Key, false, entityMap, true)); if (!useIndexerMethod) { il.Emit(OpCodes.Callvirt, getItem); } else { var propertyType = match.Value.PropertyType; if (propertyType.IsValueType) { var ctor = propertyType.GetConstructor(Type.EmptyTypes); if (ctor != null) { il.Emit(OpCodes.Newobj, ctor); il.BoxIfNeeded(propertyType); } else if (propertyType.IsPrimitive) { if (propertyType == typeof(double)) { il.Emit(OpCodes.Ldc_R8, 0.0); } else if (propertyType == typeof(float)) { il.Emit(OpCodes.Ldc_R4, 0.0f); } else { il.EmitFastInt(0); if (propertyType == typeof(long) || propertyType == typeof(ulong)) { il.Emit(OpCodes.Conv_I8); } } il.BoxIfNeeded(propertyType); } else { il.Emit(OpCodes.Ldtoken, propertyType); il.Emit(OpCodes.Call, getTypeFromHandle); il.Emit(OpCodes.Call, getDefaultValue); } } else { il.Emit(OpCodes.Ldnull); } il.Emit(OpCodes.Call, getItem); } if (typeConverter.Item1 == null) { il.EmitCastToReference(match.Key.PropertyType); } else { // Call the convert method il.Emit(OpCodes.Callvirt, typeConverter.Item2.GetMethod("ConvertForward")); } il.EmitCall(OpCodes.Callvirt, match.Key.GetSetMethod(), null); } il.Emit(OpCodes.Ret); var mapper = (PropertyMapper)method.CreateDelegate(typeof(PropertyMapper)); return(mapper); }