예제 #1
0
        private Object GetInternal(Type type, Mapping.Table table, Object id, Int32?commandTimeout, Func <IEnumerable, Object> findStrategy)
        {
            if (!table.HasPrimaryKey)
            {
                throw new Exception(String.Format("The type {0} has no primary-key property.", type == null ? table.Name : type.FullName));
            }

            if (table.PrimaryKey.ColumnSpan > 1 && id.GetType().IsPrimitive)
            {
                throw new Exception(String.Format("The type {0} has more than one primary-key property and cannot be queried by a single id value.", type == null ? table.Name : type.FullName));
            }

            String sql = table.ToSqlSelect(Factory.Dialect, Factory.Mapping.Catalog, Factory.Mapping.Schema, true);

            var args = new DynamicParameters();

            Type idType = id.GetType();

            if (table.PrimaryKey.ColumnSpan == 1 && (idType.IsPrimitive || idType == typeof(String) || idType == typeof(DateTime)))
            {
                args.Add(Enumerable.First(table.PrimaryKey.Columns).FieldName, id, null, null, null);
            }
            else
            {
                args.AddDynamicParams(id);
            }

            Object obj = null;

            if (type == null)
            {
                obj = findStrategy(Query(table.Name, sql, args, false, commandTimeout));
            }
            else if (type.IsInterface)
            {
                var res = findStrategy(Query(table.Name, sql, args, false, commandTimeout)) as IDictionary <String, Object>;
                if (res == null)
                {
                    return(null);
                }

                obj = ProxyGenerator.GetInterfaceProxy(type);
                foreach (var property in DefaultTypeMap.GetSettableProps(type))
                {
                    var val = res[property.Name];
                    property.SetValue(obj, Convert.ChangeType(val, property.PropertyType), null);
                }

                ((SqlMapperExtensions.IProxy)obj).IsDirty = false;   //reset change tracking and return
            }
            else
            {
                obj = findStrategy(Query(type, sql, args, false, commandTimeout));
            }

            return(obj);
        }
예제 #2
0
        // dr --> m
        internal static Func <IDataReader, object> GetTypeDeserializerImpl(Type mType, IDataReader reader, int startBound = 0, int length = -1, bool returnNullIfFirstMissing = false)
        {
            var dm = new DynamicMethod("Deserialize" + Guid.NewGuid().ToString(), mType, new[] { typeof(IDataReader) }, mType, true);
            var il = dm.GetILGenerator();

            il.DeclareLocal(typeof(int));
            il.DeclareLocal(mType);
            il.Emit(OpCodes.Ldc_I4_0);
            il.Emit(OpCodes.Stloc_0);

            if (length == -1)
            {
                length = reader.FieldCount - startBound;
            }

            var names = Enumerable.Range(startBound, length).Select(i => reader.GetName(i)).ToArray();

            ITypeMap typeMap = GetTypeMap(mType);

            int             index = startBound;
            ConstructorInfo specializedConstructor = null;

            bool supportInitialize = false;
            Dictionary <Type, LocalBuilder> structLocals = null;
            var types = new Type[length];

            for (int i = startBound; i < startBound + length; i++)
            {
                types[i - startBound] = reader.GetFieldType(i);
            }

            var ctor = typeMap.FindConstructor(names, types);

            if (ctor == null)
            {
                string proposedTypes = "(" + string.Join(", ", types.Select((t, i) => t.FullName + " " + names[i]).ToArray()) + ")";
                throw new InvalidOperationException($"A parameterless default constructor or one matching signature {proposedTypes} is required for {mType.FullName} materialization");
            }

            if (ctor.GetParameters().Length == 0)
            {
                il.Emit(OpCodes.Newobj, ctor);
                il.Emit(OpCodes.Stloc_1);
                supportInitialize = typeof(ISupportInitialize).IsAssignableFrom(mType);
                if (supportInitialize)
                {
                    il.Emit(OpCodes.Ldloc_1);
                    il.EmitCall(OpCodes.Callvirt, typeof(ISupportInitialize).GetMethod(nameof(ISupportInitialize.BeginInit)), null);
                }
            }
            else
            {
                specializedConstructor = ctor;
            }

            //}

            il.BeginExceptionBlock();
            if (specializedConstructor == null)
            {
                il.Emit(OpCodes.Ldloc_1);// [target]
            }

            var members = (specializedConstructor != null
                ? names.Select(n => typeMap.GetConstructorParameter(specializedConstructor, n))
                : names.Select(n => typeMap.GetMember(n))).ToList();

            // stack is now [target]

            bool first = true;
            var  allDone = il.DefineLabel();
            int  enumDeclareLocal = -1, valueCopyLocal = il.DeclareLocal(typeof(object)).LocalIndex;
            bool applyNullSetting = Settings.ApplyNullValues;

            foreach (var item in members)
            {
                if (item != null)
                {
                    if (specializedConstructor == null)
                    {
                        il.Emit(OpCodes.Dup); // stack is now [target][target]
                    }
                    Label isDbNullLabel = il.DefineLabel();
                    Label finishLabel   = il.DefineLabel();

                    il.Emit(OpCodes.Ldarg_0);                    // stack is now [target][target][reader]
                    EmitInt32(il, index);                        // stack is now [target][target][reader][index]
                    il.Emit(OpCodes.Dup);                        // stack is now [target][target][reader][index][index]
                    il.Emit(OpCodes.Stloc_0);                    // stack is now [target][target][reader][index]
                    il.Emit(OpCodes.Callvirt, Settings.GetItem); // stack is now [target][target][value-as-object]
                    il.Emit(OpCodes.Dup);                        // stack is now [target][target][value-as-object][value-as-object]
                    StoreLocal(il, valueCopyLocal);
                    Type colType    = reader.GetFieldType(index);
                    Type memberType = item.MemberType;

                    if (memberType == typeof(char) || memberType == typeof(char?))
                    {
                        il.EmitCall(OpCodes.Call, typeof(SqlHelper).GetMethod(
                                        memberType == typeof(char) ? nameof(SqlHelper.ReadChar) : nameof(SqlHelper.ReadNullableChar), BindingFlags.Static | BindingFlags.Public), null); // stack is now [target][target][typed-value]
                    }
                    else
                    {
                        il.Emit(OpCodes.Dup);                     // stack is now [target][target][value][value]
                        il.Emit(OpCodes.Isinst, typeof(DBNull));  // stack is now [target][target][value-as-object][DBNull or null]
                        il.Emit(OpCodes.Brtrue_S, isDbNullLabel); // stack is now [target][target][value-as-object]

                        // unbox nullable enums as the primitive, i.e. byte etc

                        var nullUnderlyingType = Nullable.GetUnderlyingType(memberType);
                        var unboxType          = nullUnderlyingType?.IsEnum == true ? nullUnderlyingType : memberType;

                        if (unboxType.IsEnum)
                        {
                            Type numericType = Enum.GetUnderlyingType(unboxType);
                            if (colType == typeof(string))
                            {
                                if (enumDeclareLocal == -1)
                                {
                                    enumDeclareLocal = il.DeclareLocal(typeof(string)).LocalIndex;
                                }
                                il.Emit(OpCodes.Castclass, typeof(string));                                              // stack is now [target][target][string]
                                StoreLocal(il, enumDeclareLocal);                                                        // stack is now [target][target]
                                il.Emit(OpCodes.Ldtoken, unboxType);                                                     // stack is now [target][target][enum-type-token]
                                il.EmitCall(OpCodes.Call, typeof(Type).GetMethod(nameof(Type.GetTypeFromHandle)), null); // stack is now [target][target][enum-type]
                                LoadLocal(il, enumDeclareLocal);                                                         // stack is now [target][target][enum-type][string]
                                il.Emit(OpCodes.Ldc_I4_1);                                                               // stack is now [target][target][enum-type][string][true]
                                il.EmitCall(OpCodes.Call, Settings.EnumParse, null);                                     // stack is now [target][target][enum-as-object]
                                il.Emit(OpCodes.Unbox_Any, unboxType);                                                   // stack is now [target][target][typed-value]
                            }
                            else
                            {
                                FlexibleConvertBoxedFromHeadOfStack(il, colType, unboxType, numericType);
                            }

                            if (nullUnderlyingType != null)
                            {
                                il.Emit(OpCodes.Newobj, memberType.GetConstructor(new[] { nullUnderlyingType })); // stack is now [target][target][typed-value]
                            }
                        }
                        else
                        {
                            TypeCode dataTypeCode  = Type.GetTypeCode(colType);
                            TypeCode unboxTypeCode = Type.GetTypeCode(unboxType);
                            if (colType == unboxType ||
                                dataTypeCode == unboxTypeCode ||
                                dataTypeCode == Type.GetTypeCode(nullUnderlyingType))
                            {
                                il.Emit(OpCodes.Unbox_Any, unboxType); // stack is now [target][target][typed-value]
                                //}
                            }
                            else
                            {
                                // not a direct match; need to tweak the unbox
                                FlexibleConvertBoxedFromHeadOfStack(il, colType, nullUnderlyingType ?? unboxType, null);
                                if (nullUnderlyingType != null)
                                {
                                    il.Emit(OpCodes.Newobj, unboxType.GetConstructor(new[] { nullUnderlyingType })); // stack is now [target][target][typed-value]
                                }
                            }
                        }
                    }
                    if (specializedConstructor == null)
                    {
                        // Store the value in the property/field
                        if (item.Property != null)
                        {
                            il.Emit(OpCodes.Callvirt, DefaultTypeMap.GetPropertySetter(item.Property, mType));
                        }
                        else
                        {
                            il.Emit(OpCodes.Stfld, item.Field); // stack is now [target]
                        }
                    }

                    il.Emit(OpCodes.Br_S, finishLabel); // stack is now [target]

                    il.MarkLabel(isDbNullLabel);        // incoming stack: [target][target][value]
                    if (specializedConstructor != null)
                    {
                        il.Emit(OpCodes.Pop);
                        if (item.MemberType.IsValueType)
                        {
                            int localIndex = il.DeclareLocal(item.MemberType).LocalIndex;
                            LoadLocalAddress(il, localIndex);
                            il.Emit(OpCodes.Initobj, item.MemberType);
                            LoadLocal(il, localIndex);
                        }
                        else
                        {
                            il.Emit(OpCodes.Ldnull);
                        }
                    }
                    else if (applyNullSetting && (!memberType.IsValueType || Nullable.GetUnderlyingType(memberType) != null))
                    {
                        il.Emit(OpCodes.Pop); // stack is now [target][target]
                        // can load a null with this value
                        if (memberType.IsValueType)
                        {                                                         // must be Nullable<T> for some T
                            GetTempLocal(il, ref structLocals, memberType, true); // stack is now [target][target][null]
                        }
                        else
                        {                            // regular reference-type
                            il.Emit(OpCodes.Ldnull); // stack is now [target][target][null]
                        }

                        // Store the value in the property/field
                        if (item.Property != null)
                        {
                            il.Emit(OpCodes.Callvirt, DefaultTypeMap.GetPropertySetter(item.Property, mType));
                            // stack is now [target]
                        }
                        else
                        {
                            il.Emit(OpCodes.Stfld, item.Field); // stack is now [target]
                        }
                    }
                    else
                    {
                        il.Emit(OpCodes.Pop); // stack is now [target][target]
                        il.Emit(OpCodes.Pop); // stack is now [target]
                    }

                    if (first && returnNullIfFirstMissing)
                    {
                        il.Emit(OpCodes.Pop);
                        il.Emit(OpCodes.Ldnull); // stack is now [null]
                        il.Emit(OpCodes.Stloc_1);
                        il.Emit(OpCodes.Br, allDone);
                    }

                    il.MarkLabel(finishLabel);
                }
                first = false;
                index++;
            }

            if (specializedConstructor != null)
            {
                il.Emit(OpCodes.Newobj, specializedConstructor);
            }
            il.Emit(OpCodes.Stloc_1); // stack is empty
            if (supportInitialize)
            {
                il.Emit(OpCodes.Ldloc_1);
                il.EmitCall(OpCodes.Callvirt, typeof(ISupportInitialize).GetMethod(nameof(ISupportInitialize.EndInit)), null);
            }
            //}
            il.MarkLabel(allDone);
            il.BeginCatchBlock(typeof(Exception)); // stack is Exception
            il.Emit(OpCodes.Ldloc_0);              // stack is Exception, index
            il.Emit(OpCodes.Ldarg_0);              // stack is Exception, index, reader
            LoadLocal(il, valueCopyLocal);         // stack is Exception, index, reader, value
            il.EmitCall(OpCodes.Call, typeof(SqlHelper).GetMethod(nameof(SqlHelper.ThrowDataException)), null);
            il.EndExceptionBlock();

            il.Emit(OpCodes.Ldloc_1); // stack is [rval]
            il.Emit(OpCodes.Ret);

            var funcType = System.Linq.Expressions.Expression.GetFuncType(typeof(IDataReader), mType);

            return((Func <IDataReader, object>)dm.CreateDelegate(funcType));
        }
예제 #3
0
 public ExplicitTypeMap(Type type, IReadOnlyDictionary <string, string> columnsMap)
 {
     _columnsMap    = columnsMap;
     _type          = type;
     _defaultMapper = new DefaultTypeMap(_type);
 }
예제 #4
0
        public void Customize(IFixture fixture)
        {
            var builders = new DefaultTypeMap().Select(map => new HydratorAdapter(map));

            fixture.Customizations.Add(new CompositeSpecimenBuilder(builders));
        }