// 导航属性 private void Deserialize_Navigation(object model, string typeName) { // CRM_SaleOrder.Client Type pType = model.GetType(); TypeRuntimeInfo runtime = TypeRuntimeInfoCache.GetRuntimeInfo(pType); if (string.IsNullOrEmpty(typeName)) { typeName = pType.Name; } foreach (var kvp in _define.NavDescriptors) { var descriptor = kvp.Value; if (descriptor.Count == 0) { continue; } string keyName = typeName + "." + descriptor.Name; if (keyName != kvp.Key) { continue; } var navWrapper = runtime.GetWrapper(descriptor.Name); if (navWrapper == null) { continue; } Type navType = navWrapper.DataType; Func <IDataRecord, object> func = null; if (!_funcCache.TryGetValue(keyName, out func)) { func = GetDeserializer(navType, _reader, _define.Columns, descriptor.Start, descriptor.Start + descriptor.Count); _funcCache[keyName] = func; } object navModel = func(_reader); navWrapper.Set(model, navModel); TypeRuntimeInfo navRuntime = TypeRuntimeInfoCache.GetRuntimeInfo(navType); if (navRuntime.NavWrappers.Count > 0) { Deserialize_Navigation(navModel, keyName); } } }
/// <summary> /// 将 <see cref="IDataRecord"/> 映射为实体 /// </summary> /// <typeparam reader="T">数据源</typeparam> /// <param name="reader">数据源</param> /// <param name="define">命令定义</param> /// <returns></returns> public static T ToModel <T>(this IDataRecord reader, CommandDefine define = null) { object obj = null; object[] values = null; int index = 0; // 基元类初始化 ######################## if (Reflection.TypeUtils.IsPrimitive(typeof(T))) { //if(reader.IsDBNull(0)) return default(T) //obj = reader.GetValue(0); //return obj is DBNull ? default(T) : (T)obj; return(reader.IsDBNull(0) ? default(T) : (T)reader.GetValue(0)); } // 匿名类初始化 ######################## TypeRuntimeInfo runtime = TypeRuntimeInfoCache.GetRuntimeInfo <T>(); Inte.XFramework.Reflection.Emit.ConstructorInvoker ctor = runtime.ConstructInvoker; if (runtime.IsAnonymousType) { values = new object[reader.FieldCount]; reader.GetValues(values); for (index = 0; index < values.Length; ++index) { if (values[index] is DBNull) { values[index] = null; } } return((T)ctor.Invoke(values)); } // 实体类初始化 ######################## T model = (T)ctor.Invoke(); values = new object[reader.FieldCount]; reader.GetValues(values); // 计算导航属性所占用的索引,这些索引对应的值不会赋给 T 实体 var sc = define as CommandDefine_Select; if (sc == null || (sc.NavDescriptors != null && sc.NavDescriptors.Count == 0)) { // 直接跑SQL,则不解析导航属性 for (int i = 0; i < reader.FieldCount; ++i) { obj = values[i]; if (obj == DBNull.Value) { continue; } string name = reader.GetName(i); var wrapper = runtime.GetWrapper(name) as MemberAccessWrapper; if (wrapper != null) { SetProperty(model, wrapper, obj); } } } else { // 使用表达式查询,解析导航属性 bool nav = sc.NavDescriptors.Any(x => x.Value.Count > 0); int min = nav ? sc.NavDescriptors.Min(x => x.Value.Start) : 0; // 第一层 index = -1; foreach (var kvp in sc.Columns) { index += 1; obj = values[index]; if (obj == DBNull.Value) { continue; } if (nav && index >= min) { break; } var wrapper = runtime.GetWrapper(kvp.Value.Name) as MemberAccessWrapper; if (wrapper != null) { SetProperty(model, wrapper, obj); } } // 递归导航属性 if (runtime.NavWrappers.Count > 0) { ToModel_Navigation(model, values, sc, string.Empty); } } return(model); }
// 导航属性 private static void ToModel_Navigation(object model, object[] values, CommandDefine_Select define, string typeName) { // CRM_SaleOrder.Client Type pType = model.GetType(); TypeRuntimeInfo runtime = TypeRuntimeInfoCache.GetRuntimeInfo(pType); if (string.IsNullOrEmpty(typeName)) { typeName = pType.Name; } foreach (var kvp in runtime.NavWrappers) { string keyName = typeName + "." + kvp.Key; ColumnNavDescriptor descriptor = null; define.NavDescriptors.TryGetValue(keyName, out descriptor); if (descriptor == null) { continue; } // 实例化这个导航属性并且给它赋值 var navWrapper = kvp.Value; Type navType = navWrapper.DataType; TypeRuntimeInfo navRuntime = TypeRuntimeInfoCache.GetRuntimeInfo(navType); object navModel = navRuntime.ConstructInvoker.Invoke(); if (descriptor.Count > 0) { int index = -1; foreach (var c_kvp in define.Columns) { index += 1; if (index < descriptor.Start) { continue; } if (index > (descriptor.Start + descriptor.Count)) { break; } object obj = values[index]; if (obj == DBNull.Value) { continue; } var wrapper = navRuntime.GetWrapper(c_kvp.Value.Name) as MemberAccessWrapper; if (wrapper != null) { SetProperty(navModel, wrapper, obj); } } } SetProperty(model, navWrapper, navModel); if (navRuntime.NavWrappers.Count > 0) { ToModel_Navigation(navModel, values, define, keyName); } } }
private static Func <IDataRecord, object> GetDeserializer(Type modelType, IDataRecord reader, IDictionary <string, Column> columns = null, int start = 0, int?end = null) { string methodName = Guid.NewGuid().ToString(); DynamicMethod dm = new DynamicMethod(methodName, typeof(object), new[] { typeof(IDataRecord) }, true); ILGenerator g = dm.GetILGenerator(); TypeRuntimeInfo runtime = TypeRuntimeInfoCache.GetRuntimeInfo(modelType); var model = g.DeclareLocal(modelType); g.Emit(OpCodes.Newobj, runtime.ConstructInvoker.Constructor); g.Emit(OpCodes.Stloc, model); if (end == null) { end = reader.FieldCount; } for (int index = start; index < end; index++) { string keyName = reader.GetName(index); if (columns != null) { Column column = null; columns.TryGetValue(keyName, out column); keyName = column != null ? column.Name : string.Empty; } var wrapper = runtime.GetWrapper(keyName);// as MemberAccessWrapper; if (wrapper == null) { continue; } var isDBNullLabel = g.DefineLabel(); g.Emit(OpCodes.Ldarg_0); g.Emit(OpCodes.Ldc_I4, index); g.Emit(OpCodes.Callvirt, _isDBNull); g.Emit(OpCodes.Brtrue, isDBNullLabel); var m_method = GetReaderMethod(wrapper.DataType); g.Emit(OpCodes.Ldloc, model); g.Emit(OpCodes.Ldarg_0); g.Emit(OpCodes.Ldc_I4, index); g.Emit(OpCodes.Callvirt, m_method); Type dataType = wrapper.DataType; Type nullUnderlyingType = dataType.IsGenericType ? Nullable.GetUnderlyingType(dataType) : null; Type unboxType = nullUnderlyingType != null ? nullUnderlyingType : dataType; if (unboxType == typeof(byte[]) || (m_method == _getValue && dataType != typeof(object))) { g.Emit(OpCodes.Castclass, dataType); } if (nullUnderlyingType != null) { g.Emit(OpCodes.Newobj, dataType.GetConstructor(new[] { nullUnderlyingType })); } if (wrapper.Member.MemberType == MemberTypes.Field) { g.Emit(OpCodes.Stfld, wrapper.FieldInfo); } else { g.Emit(OpCodes.Callvirt, wrapper.SetMethod); } g.MarkLabel(isDBNullLabel); } g.Emit(OpCodes.Ldloc, model); g.Emit(OpCodes.Ret); var func = (Func <IDataRecord, object>)dm.CreateDelegate(typeof(Func <IDataRecord, object>)); return(func); }