// 导航属性
        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);
                }
            }
        }
Exemple #2
0
        /// <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);
        }
Exemple #3
0
        // 导航属性
        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);
        }