Esempio n. 1
0
        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);
        }
Esempio n. 2
0
        private static void DefineIndexerProperty(PropertyInfo property, TypeBuilder typeBuilder, FieldInfo field, Type objectType, bool ignoreMappings, IEntityMap entityMap)
        {
            // create the new property.
            var propertyBuilder = typeBuilder.DefineProperty(property.Name, PropertyAttributes.HasDefault, property.PropertyType, null);

            // The property "set" and property "get" methods require a special set of attributes.
            //var getSetAttr = MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig | MethodAttributes.Virtual;
            const MethodAttributes getSetAttr = MethodAttributes.Private | MethodAttributes.HideBySig | MethodAttributes.NewSlot | MethodAttributes.Virtual | MethodAttributes.Final | MethodAttributes.SpecialName;
            var columnName = MappingFactory.GetPropertyOrColumnName(property, ignoreMappings, entityMap, true);

            // create the getter if we can read.
            if (property.CanRead)
            {
                var getItemMethod = objectType.GetMethod("get_Item", new[] { typeof(string) });

                var typeConverter = MappingFactory.GetTypeConverter(getItemMethod.ReturnType, property, entityMap);

                // create the get method for the property.
                var getMethodName = "get_" + property.Name;
                var getMethod     = typeBuilder.DefineMethod(getMethodName, getSetAttr, property.PropertyType, Type.EmptyTypes);

                // get the IL generator to generate the required IL.
                ILGenerator il = getMethod.GetILGenerator();

                if (typeConverter.Item1 != null)
                {
                    //	New the converter
                    il.Emit(OpCodes.Newobj, typeConverter.Item1.GetConstructor(Type.EmptyTypes));
                }

                // load the first argument (the instance itself) and the field.
                il.Emit(OpCodes.Ldarg_0);
                il.Emit(OpCodes.Ldfld, field);
                il.Emit(OpCodes.Ldstr, columnName);
                il.Emit(OpCodes.Callvirt, getItemMethod);
                if (typeConverter.Item1 == null)
                {
                    il.EmitCastToReference(property.PropertyType);
                }
                else
                {
                    //	Call the convert method
                    il.Emit(OpCodes.Callvirt, typeConverter.Item2.GetMethod("ConvertForward"));
                }
                il.Emit(OpCodes.Ret);

                // set the method.
                propertyBuilder.SetGetMethod(getMethod);
                typeBuilder.DefineMethodOverride(getMethod, property.ReflectedType.GetMethod(getMethodName));
            }

            // create the setter if we can read.
            if (property.CanWrite)
            {
                var setItemMethod = objectType.GetMethod("set_Item", new[] { typeof(string), typeof(object) });

                var typeConverter = MappingFactory.GetTypeConverter(setItemMethod.GetParameters()[1].ParameterType, property, entityMap);

                // create the set method of the property.
                var setMethodName = "set_" + property.Name;
                var setMethod     = typeBuilder.DefineMethod(setMethodName, getSetAttr, null, new[] { property.PropertyType });

                // get the IL generator to generate some IL.
                ILGenerator il = setMethod.GetILGenerator();

                // load the first argument (instance itself) and the field.
                il.Emit(OpCodes.Ldarg_0);
                il.Emit(OpCodes.Ldfld, field);
                il.Emit(OpCodes.Ldstr, columnName);

                if (typeConverter.Item1 != null)
                {
                    //	New the converter
                    il.Emit(OpCodes.Newobj, typeConverter.Item1.GetConstructor(Type.EmptyTypes));
                }

                // load the second argument (holding the value).
                il.Emit(OpCodes.Ldarg_1);
                if (typeConverter.Item1 != null)
                {       //	Call the convert method
                    il.Emit(OpCodes.Callvirt, typeConverter.Item2.GetMethod("ConvertBackward"));
                }
                else
                {
                    il.BoxIfNeeded(property.PropertyType);
                }
                // directly call the inner object's get method of the property.
                il.Emit(OpCodes.Callvirt, setItemMethod);
                il.Emit(OpCodes.Ret);

                propertyBuilder.SetSetMethod(setMethod);
                typeBuilder.DefineMethodOverride(setMethod, property.ReflectedType.GetMethod(setMethodName));
            }
        }
Esempio n. 3
0
        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);
        }