/// <summary> /// 初始化 <see cref="ColumnExpressionVisitor"/> 类的新实例 /// </summary> /// <param name="provider">查询语义提供者</param> /// <param name="aliases">表别名集合</param> /// <param name="dbQuery">查询语义</param> public ColumnExpressionVisitor(IDbQueryProvider provider, TableAlias aliases, IDbQueryableInfo_Select dbQuery) : base(provider, aliases, dbQuery.Select.Expressions != null ? dbQuery.Select.Expressions[0] : null) { _provider = provider; _aliases = aliases; _dbQuery = dbQuery; _groupBy = dbQuery.GroupBy; _include = dbQuery.Includes; if (_pickColumns == null) { _pickColumns = new DbColumnCollection(); } _navDescriptors = new NavDescriptorCollection(); _navDescriptorKeys = new List <string>(10); }
/// <summary> /// 生成实体映射委托 /// </summary> /// <param name="type">实体类型</param> /// <param name="reader">数据读取器</param> /// <param name="columns">字段列描述</param> /// <param name="start">开始索引</param> /// <param name="end">结束索引</param> /// <returns></returns> public Func <IDataRecord, object> GetTypeDeserializer(Type type, IDataRecord reader, DbColumnCollection columns = null, int start = 0, int?end = null) { //// specify a new assembly name //var assemblyName = new AssemblyName("TZM.Deserialize"); //// create assembly builder //var assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.RunAndSave); //// create module builder //var moduleBuilder = assemblyBuilder.DefineDynamicModule(assemblyName.Name, assemblyName.Name + ".dll", true); //// create type builder for a class //var typeBuilder = moduleBuilder.DefineType("TZM.Deserialize.Deserializer", TypeAttributes.Public); //// create method builder //var methodBuilder = typeBuilder.DefineMethod("GetModel", // MethodAttributes.Public | MethodAttributes.Static, // typeof(object), // new Type[] { typeof(IDataRecord) // }); TypeRuntimeInfo typeRuntime = TypeRuntimeInfoCache.GetRuntimeInfo(type); DynamicMethod method = new DynamicMethod(string.Format("Deserialize{0}", Guid.NewGuid()), typeof(object), new Type[] { typeof(IDataRecord) }, true); //ILGenerator il = methodBuilder.GetILGenerator(); ILGenerator il = method.GetILGenerator(); il.DeclareLocal(typeof(int)); // [0] int index il.DeclareLocal(type); // [1] {type} il.Emit(OpCodes.Ldc_I4_0); il.Emit(OpCodes.Stloc_0); // 有参构造函数 ConstructorInfo specializedConstructor = null; if (type.IsValueType) { // 如果是值类型,则将值类型设置为空或者0 il.Emit(OpCodes.Ldloca_S, (byte)1); il.Emit(OpCodes.Initobj, type); } else { var ctor = typeRuntime.Constructor.Constructor; if (ctor.GetParameters().Length > 0) { specializedConstructor = ctor; } else { // 如果不是匿名类或者只有无参构造函数,则new一个对象 il.Emit(OpCodes.Newobj, ctor); il.Emit(OpCodes.Stloc_1); // [1] {type}=new {type} } } // try ##### il.BeginExceptionBlock(); if (specializedConstructor == null) { il.Emit(OpCodes.Ldloc_1); // [target] } // stack is now [target] Label finishLabel = il.DefineLabel(); Label loadNullLabel = il.DefineLabel(); int enumDeclareLocal = -1; if (end == null) { end = reader.FieldCount; } for (int index = start; index < end; index++) { // 找出对应DataReader中的字段名 string memberName = reader.GetName(index); if (columns != null) { DbColumn column = null; columns.TryGetValue(memberName, out column); memberName = column != null ? column.Name : string.Empty; } // 本地变量赋值 il.Emit(OpCodes.Ldc_I4, index); // [target][index] il.Emit(OpCodes.Stloc_0); // [target] // 如果导航属性分割列=DbNull,那么此导航属性赋空值 if (memberName == Constant.NAVIGATION_SPLITON_NAME) { il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldc_I4, index); il.Emit(OpCodes.Callvirt, _isDBNull); il.Emit(OpCodes.Brtrue_S, loadNullLabel); } var m = typeRuntime.GetMember(memberName); if (m == null) { continue; } if (specializedConstructor == null) { il.Emit(OpCodes.Dup); // stack is now [target][target] } // 数据字段类型 Type myFieldType = reader.GetFieldType(index); Type myFieldType2 = myFieldType; // 实体属性类型 Type memberType = m.DataType; MethodInfo getFieldValue = this.GetReaderMethod(myFieldType, memberType, ref myFieldType2); if (myFieldType != myFieldType2) { myFieldType = myFieldType2; } Label isDbNullLabel = il.DefineLabel(); Label nextLoopLabel = il.DefineLabel(); // 判断字段是否是 DbNull il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldc_I4, index); il.Emit(OpCodes.Callvirt, _isDBNull); il.Emit(OpCodes.Brtrue, isDbNullLabel); // =>DataReader.Getxx(index) il.Emit(OpCodes.Ldarg_0); // stack is now [target][target][reader] if (getFieldValue.DeclaringType != typeof(IDataRecord)) { il.Emit(OpCodes.Castclass, getFieldValue.DeclaringType); // (SqlDataReader)IDataReader } il.Emit(OpCodes.Ldc_I4, index); // stack is now [target][target][reader][index] il.Emit(OpCodes.Callvirt, getFieldValue); // stack is now [target][target][value-or-object] if (memberType == typeof(char) || memberType == typeof(char?)) { il.EmitCall(OpCodes.Call, memberType == typeof(char) ? _readChar : _readNullChar, null); // stack is now [target][target][typed-value] } else { // unbox nullable enums as the primitive, i.e. byte etc var nullUnderlyingType = Nullable.GetUnderlyingType(memberType); var unboxType = nullUnderlyingType != null && nullUnderlyingType.IsEnum ? nullUnderlyingType : memberType; if (unboxType.IsEnum) { Type numericType = Enum.GetUnderlyingType(unboxType); if (myFieldType != typeof(string)) { ConvertBox(il, myFieldType, unboxType, numericType); } else { if (enumDeclareLocal == -1) { enumDeclareLocal = il.DeclareLocal(typeof(string)).LocalIndex; } il.Emit(OpCodes.Castclass, typeof(string)); // stack is now [target][target][string] il.StoreLocal(enumDeclareLocal); // stack is now [target][target] il.Emit(OpCodes.Ldtoken, unboxType); // stack is now [target][target][enum-type-token] il.EmitCall(OpCodes.Call, _typeFromHandle, null); // stack is now [target][target][enum-type] il.LoadLocal(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, _enumParse, null); // stack is now [target][target][enum-as-object] il.Emit(OpCodes.Unbox_Any, unboxType); // stack is now [target][target][typed-value] } // new Nullable<TValue>(TValue) if (nullUnderlyingType != null) { EmitNewNullable(il, memberType); // stack is now [target][target][typed-value] } } else if (memberType.FullName == _linqBinaryName) { var ctor = memberType.GetConstructor(new Type[] { typeof(byte[]) }); il.Emit(OpCodes.Unbox_Any, typeof(byte[])); // stack is now [target][target][byte-array] il.Emit(OpCodes.Newobj, ctor); // stack is now [target][target][binary] } else { bool noBoxed = myFieldType == unboxType || myFieldType == nullUnderlyingType; // myFieldType和实体属性类型一致, 如果用 DataReader.GetValue,则要强制转换{object}为实体属性定义的类型 bool useCast = noBoxed && getFieldValue == _getValue && unboxType != typeof(object); if (useCast) { il.EmitCast(nullUnderlyingType ?? unboxType); // stack is now [target][target][typed-value] } // myFieldType和实体属性类型不一致,需要做类型转换 if (!noBoxed) { if (getFieldValue == _getValue && myFieldType.IsValueType) { il.Emit(OpCodes.Unbox_Any, myFieldType); // stack is now [target][target][value] } // not a direct match; need to tweak the unbox ConvertBox(il, myFieldType, nullUnderlyingType ?? unboxType, null); } // new Nullable<TValue>(TValue) if (nullUnderlyingType != null) { EmitNewNullable(il, memberType); // stack is now [target][target][typed-value] } } } if (specializedConstructor == null) { // Store the value in the property/field if (m.MemberType == MemberTypes.Field) { il.Emit(OpCodes.Stfld, m.Member as FieldInfo); // stack is now [target] } else { MethodInfo setMethod = (m as PropertyAccessor).SetMethod; il.Emit(type.IsValueType ? OpCodes.Call : OpCodes.Callvirt, setMethod);// stack is now [target] } } il.Emit(OpCodes.Br_S, nextLoopLabel); // stack is now [target] il.MarkLabel(isDbNullLabel); // incoming stack: [target][target] if (specializedConstructor == null) { il.Emit(OpCodes.Pop); // stack is now [target] } else { // DbNull,将NULL或者0推到栈顶 if (!m.DataType.IsValueType) { il.Emit(OpCodes.Ldnull); } else { int localIndex = il.DeclareLocal(m.DataType).LocalIndex; il.LoadLocalAddress(localIndex); il.Emit(OpCodes.Initobj, m.DataType); il.LoadLocal(localIndex); } } il.MarkLabel(nextLoopLabel); } if (specializedConstructor != null) { il.Emit(OpCodes.Newobj, specializedConstructor); } il.Emit(OpCodes.Stloc_1); // stack is empty // 直接跳到结束标签返回实体 il.Emit(OpCodes.Br, finishLabel); // 将 null 赋值给实体 il.MarkLabel(loadNullLabel); il.Emit(OpCodes.Pop); il.Emit(OpCodes.Ldnull); il.Emit(OpCodes.Stloc_1); il.MarkLabel(finishLabel); 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 il.EmitCall(OpCodes.Call, _throwException, null); il.EndExceptionBlock(); il.Emit(OpCodes.Ldloc_1); // stack is [rval] il.Emit(OpCodes.Ret); //// then create the whole class type //typeBuilder.CreateType(); //// save assembly //assemblyBuilder.Save(assemblyName.Name + ".dll"); return((Func <IDataRecord, object>)method.CreateDelegate(typeof(Func <IDataRecord, object>))); }