示例#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
        private static void DefineProperties(Type objectType, TypeBuilder typeBuilder, FieldInfo field, Type interfaceType, DynamicProxyType proxyType, bool ignoreMappings)
        {
            var entityMap = MappingFactory.GetEntityMap(interfaceType);

            foreach (var property in Reflector.GetAllProperties(interfaceType))
            {
                // check if we can support the wrapping.
                var propertyName   = MappingFactory.GetPropertyOrColumnName(property, ignoreMappings, entityMap, false);
                var objectProperty = objectType != null?objectType.GetProperty(propertyName) : null;

                if (objectProperty != null && ((property.CanRead && !objectProperty.CanRead) || (property.CanWrite && !objectProperty.CanWrite)))
                {
                    throw new InvalidCastException("Can't cast because the property is missing or does not have the required implementation.");
                }

                // check the property types.
                if (objectProperty != null && objectProperty.PropertyType != property.PropertyType)
                {
                    throw new InvalidCastException("Can't cast because property types do not match.");
                }

                // define the property.
                if (proxyType == DynamicProxyType.FullIndexer)
                {
                    DefineIndexerProperty(property, typeBuilder, field, objectType, ignoreMappings, entityMap);
                }
                else if (proxyType == DynamicProxyType.SimpleIndexer && IsWrappable(property, entityMap))
                {
                    DefineIndexerProperty(property, typeBuilder, field, objectType, ignoreMappings, entityMap);
                }
                else if (proxyType == DynamicProxyType.Guard)
                {
                    DefineGuardedProperty(property, typeBuilder, field, objectType, ignoreMappings, entityMap);
                }
                else if (objectProperty != null)
                {
                    DefineProperty(property, typeBuilder, field, objectType, objectProperty);
                }
                else
                {
                    DefineDefaultProperty(property, typeBuilder);
                }
            }
        }
示例#3
0
        private static void DefineGuardedProperty(PropertyInfo property, TypeBuilder typeBuilder, FieldInfo field, Type objectType, bool ignoreMappings, IEntityMap entityMap)
        {
            // create the new property.
            var propertyBuilder = typeBuilder.DefineProperty(property.Name, System.Reflection.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;
            var 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)
            {
                // 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();

                // directly call the inner object's get method of the property.
                Type elementType;
                if (Reflector.IsDataEntityList(property.PropertyType, out elementType))
                {
                    var isInterface      = property.PropertyType.GetGenericTypeDefinition() == typeof(IList <>);
                    var asReadOnlyMethod = typeof(ObjectExtensions).GetMethods(BindingFlags.Public | BindingFlags.Static).Where(m => m.Name == "AsReadOnly").First(m => m.GetParameters()[0].ParameterType.Name == (isInterface ? "IList`1" : "List`1"));

                    var result = il.DeclareLocal(property.PropertyType);

                    // load the first argument (the instance itself) and the field.
                    il.Emit(OpCodes.Ldarg_0);
                    il.Emit(OpCodes.Ldfld, field);
                    il.EmitCall(OpCodes.Callvirt, property.GetGetMethod(), null);

                    il.Emit(OpCodes.Call, asReadOnlyMethod.MakeGenericMethod(elementType));

                    il.Emit(OpCodes.Stloc_0, result);
                    il.Emit(OpCodes.Ldloc_0);
                }
                else if (Reflector.IsDataEntity(property.PropertyType))
                {
                    var asReadOnlyMethod = typeof(ObjectExtensions).GetMethods(BindingFlags.Public | BindingFlags.Static).Where(m => m.Name == "AsReadOnly").First(m => m.GetParameters()[0].ParameterType.IsGenericParameter);

                    var result = il.DeclareLocal(property.PropertyType);

                    // load the first argument (the instance itself) and the field.
                    il.Emit(OpCodes.Ldarg_0);
                    il.Emit(OpCodes.Ldfld, field);
                    il.EmitCall(OpCodes.Callvirt, property.GetGetMethod(), null);

                    il.Emit(OpCodes.Call, asReadOnlyMethod.MakeGenericMethod(property.PropertyType));

                    il.Emit(OpCodes.Stloc_0, result);
                    il.Emit(OpCodes.Ldloc_0);
                }
                else if (property.DeclaringType.InheritsFrom(typeof(ITrackableDataEntity)) && property.PropertyType == typeof(ObjectState) && property.Name == "ObjectState")
                {
                    il.Emit(OpCodes.Ldc_I4, (int)ObjectState.ReadOnly);
                }
                else
                {
                    // load the first argument (the instance itself) and the field.
                    il.Emit(OpCodes.Ldarg_0);
                    il.Emit(OpCodes.Ldfld, field);
                    il.EmitCall(OpCodes.Callvirt, property.GetGetMethod(), null);
                }

                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)
            {
                // create the set method of the property.
                var setMethodName = "set_" + property.Name;
                var setMethod     = typeBuilder.DefineMethod(setMethodName, getSetAttr, null, new Type[] { 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.Newobj, typeof(NotSupportedException).GetConstructor(Type.EmptyTypes));
                il.Emit(OpCodes.Throw);

                propertyBuilder.SetSetMethod(setMethod);
                typeBuilder.DefineMethodOverride(setMethod, property.ReflectedType.GetMethod(setMethodName));
            }
        }
示例#4
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));
            }
        }
示例#5
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);
        }
示例#6
0
文件: Mapper.cs 项目: MingLu8/Nemo
        private static PropertyMapper GenerateDelegate(Type sourceType, Type targetType)
        {
            var method = new DynamicMethod("Map_" + sourceType.FullName + "_" + targetType.FullName, null, new[] { typeof(object), typeof(object) }, true);
            var il     = method.GetILGenerator();

            var sourceProperties = Reflector.GetAllProperties(sourceType);
            var targetProperties = Reflector.GetAllProperties(targetType);

            var entityMap = MappingFactory.GetEntityMap(targetType);

            var matches = sourceProperties.CrossJoin(targetProperties).Where(t => (t.Item2.Name == t.Item3.Name || t.Item2.Name == MappingFactory.GetPropertyOrColumnName(t.Item3, false, entityMap, false)) &&
                                                                             t.Item2.PropertyType == t.Item3.PropertyType &&
                                                                             t.Item2.PropertyType.IsPublic &&
                                                                             t.Item3.PropertyType.IsPublic
                                                                             //&& (t.Item3.PropertyType.IsValueType || t.Item3.PropertyType == typeof(string))
                                                                             && t.Item2.CanRead && t.Item3.CanWrite);

            foreach (var match in matches)
            {
                il.Emit(OpCodes.Ldarg_1);
                il.EmitCastToReference(targetType);
                il.Emit(OpCodes.Ldarg_0);
                il.EmitCastToReference(sourceType);
                il.Emit(OpCodes.Callvirt, match.Item2.GetGetMethod());
                il.Emit(OpCodes.Callvirt, match.Item3.GetSetMethod());
            }
            il.Emit(OpCodes.Ret);

            var mapper = (PropertyMapper)method.CreateDelegate(typeof(PropertyMapper));

            return(mapper);
        }