示例#1
0
文件: Mapper.cs 项目: tahiralvi/Nemo
        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);
        }
示例#2
0
文件: Mapper.cs 项目: MingLu8/Nemo
        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);
        }