/// <summary> /// 选择所有的字段 /// </summary> /// <param name="type">实体类型</param> /// <param name="alias">表别名</param> /// <param name="node">节点</param> /// <returns></returns> protected virtual Expression VisitAllMember(Type type, string alias, Expression node = null) { if (_groupBy != null && node != null && node.IsGrouping()) { // select g.Key LambdaExpression keySelector = _groupBy.Expressions[0] as LambdaExpression; return(this.Visit(keySelector.Body)); } else { TypeRuntimeInfo typeRuntime = TypeRuntimeInfoCache.GetRuntimeInfo(type); foreach (var item in typeRuntime.Members) { var m = item as FieldAccessorBase; if (m == null || !m.IsDbField) { continue; } _builder.AppendMember(alias, m.Member, type); this.AddSelectedColumn(m.Member, type); } } return(node); }
/// <summary> /// 实例化<see cref="TypeDeserializer"/> 类的新实例 /// </summary> /// <param name="context">当前查询上下文</param> /// <param name="reader">DataReader</param> /// <param name="map">SQL 命令描述</param> /// <param name="entityType">单个实体类型</param> internal TypeDeserializer_Internal(IDbContext context, IDataReader reader, IMapDescriptor map, Type entityType) { _map = map; _reader = reader; _context = context; _deserializers = new Dictionary <string, Func <IDataRecord, object> >(8); _manyNavigationKeys = new Dictionary <string, HashSet <string> >(8); _entityType = entityType; _isDynamic = _entityType == typeof(ExpandoObject) || _entityType == typeof(object); _typeRuntime = TypeRuntimeInfoCache.GetRuntimeInfo(entityType); _deserializerImpl = ((DbQueryProvider)context.Provider).TypeDeserializerImpl; }
// 添加额外列,用来判断整个(左)连接记录是否为空 private void AddSplitOnColumn(MemberExpression m, string alias) { TypeRuntimeInfo typeRuntime = TypeRuntimeInfoCache.GetRuntimeInfo(m.Expression.Type); var attribute = typeRuntime.GetMemberAttribute <ForeignKeyAttribute>(m.Member.Name); string keyName = attribute.OuterKeys.FirstOrDefault(a => !a.StartsWith(AppConst.CONSTANT_FOREIGNKEY, StringComparison.Ordinal)); _builder.Append("CASE WHEN "); _builder.AppendMember(alias, keyName); _builder.Append(" IS NULL THEN NULL ELSE "); _builder.AppendMember(alias, keyName); _builder.Append(" END"); // 选择字段 string newName = _selectedColumns.Add(AppConst.NAVIGATION_SPLITON_NAME); _builder.AppendAs(newName); _builder.Append(','); _builder.AppendNewLine(); }
/// <summary> /// 添加导航属性关联 /// </summary> protected override void TanslateNavMember() { if (this.NavMembers == null || this.NavMembers.Count == 0) { return; } // 如果有一对多的导航属性,肯定会产生嵌套查询。那么内层查询别名肯定是t0,所以需要清掉 if (this.HasMany) { _aliasGenerator = new AliasGenerator(_aliasGenerator.ReserveQty); } //开始产生 USING 子句 ISqlBuilder jf = this.JoinFragment; int index = -1; // 未生成USING子句 if (_aliasGenerator.ReserveQty <= 1) { jf.AppendNewLine(); jf.Append(_keywordName); } else { jf.Append(','); jf.AppendNewLine(); } foreach (var nav in this.NavMembers) { index++; string key = nav.Key; MemberExpression m = nav.Expression; TypeRuntimeInfo typeRuntime = TypeRuntimeInfoCache.GetRuntimeInfo(m.Expression.Type); ForeignKeyAttribute attribute = typeRuntime.GetMemberAttribute <ForeignKeyAttribute>(m.Member.Name); string innerKey = string.Empty; string outerKey = key; string innerAlias = string.Empty; if (!m.Expression.Visitable()) { innerKey = m.Expression.NodeType == ExpressionType.Parameter ? (m.Expression as ParameterExpression).Name : (m.Expression as MemberExpression).Member.Name; } else { MemberExpression mLeft = null; if (m.Expression.NodeType == ExpressionType.MemberAccess) { mLeft = m.Expression as MemberExpression; } else if (m.Expression.NodeType == ExpressionType.Call) { mLeft = (m.Expression as MethodCallExpression).Object as MemberExpression; } string name = TypeRuntimeInfoCache.GetRuntimeInfo(mLeft.Type).TableFullName; innerAlias = _aliasGenerator.GetJoinTableAlias(name); if (string.IsNullOrEmpty(innerAlias)) { string keyLeft = mLeft.GetKeyWidthoutAnonymous(); if (this.NavMembers.Contains(keyLeft)) { innerKey = keyLeft; } innerAlias = _aliasGenerator.GetNavTableAlias(innerKey); } } string alias1 = !string.IsNullOrEmpty(innerAlias) ? innerAlias : _aliasGenerator.GetTableAlias(innerKey); string alias2 = _aliasGenerator.GetNavTableAlias(outerKey); // 补充与USING字符串同等间距的空白 if (_aliasGenerator.ReserveQty > 1 || index > 0) { jf.Append(_pad); } Type type = m.Type; var typeRumtime2 = TypeRuntimeInfoCache.GetRuntimeInfo(type); if (type.IsGenericType) { type = type.GetGenericArguments()[0]; } jf.AppendTable(typeRumtime2.TableSchema, typeRumtime2.TableName, typeRumtime2.IsTemporary); jf.Append(' '); jf.Append(alias2); if (_onPhrase.Length > 0) { _onPhrase.Append(" AND "); } for (int i = 0; i < attribute.InnerKeys.Length; i++) { if (attribute.InnerKeys[i].StartsWith(AppConst.CONSTANT_FOREIGNKEY, StringComparison.Ordinal)) { _onPhrase.Append(attribute.InnerKeys[i].Substring(7)); } else { _onPhrase.Append(alias1); _onPhrase.Append('.'); _onPhrase.AppendMember(attribute.InnerKeys[i]); } _onPhrase.Append(" = "); if (attribute.OuterKeys[i].StartsWith(AppConst.CONSTANT_FOREIGNKEY, StringComparison.Ordinal)) { _onPhrase.Append(attribute.OuterKeys[i].Substring(7)); } else { _onPhrase.Append(alias2); _onPhrase.Append('.'); _onPhrase.AppendMember(attribute.OuterKeys[i]); } } if (nav.Predicate != null) { string alias = _aliasGenerator.GetNavTableAlias(nav.Key); var visitor = new NavPredicateExpressionVisitor(_aliasGenerator, _onPhrase, alias); visitor.Visit(nav.Predicate); } if (index < this.NavMembers.Count - 1) { jf.Append(','); jf.AppendNewLine(); } } }
/// <summary> /// 添加导航属性关联 /// </summary> protected override void TanslateNavMember() { if (base.NavMembers == null || base.NavMembers.Count == 0) { return; } // 如果有一对多的导航属性,肯定会产生嵌套查询。那么内层查询别名肯定是t0,所以需要清掉 if (this.HasMany) { _ag = new AliasGenerator(_ag.ReserveQty); } //开始产生LEFT JOIN 子句 ISqlBuilder builder = this.JoinFragment; foreach (var nav in base.NavMembers) { string key = nav.Key; MemberExpression m = nav.Expression; TypeRuntimeInfo typeRuntime = TypeRuntimeInfoCache.GetRuntimeInfo(m.Expression.Type); ForeignKeyAttribute attribute = typeRuntime.GetMemberAttribute <ForeignKeyAttribute>(m.Member.Name); string innerKey = string.Empty; string outerKey = key; string innerAlias = string.Empty; if (!m.Expression.Visitable()) { innerKey = m.Expression.NodeType == ExpressionType.Parameter ? (m.Expression as ParameterExpression).Name : (m.Expression as MemberExpression).Member.Name; } else { MemberExpression mLeft = null; if (m.Expression.NodeType == ExpressionType.MemberAccess) { mLeft = m.Expression as MemberExpression; } else if (m.Expression.NodeType == ExpressionType.Call) { mLeft = (m.Expression as MethodCallExpression).Object as MemberExpression; } string name = TypeRuntimeInfoCache.GetRuntimeInfo(mLeft.Type).TableFullName; innerAlias = _ag.GetJoinTableAlias(name); if (string.IsNullOrEmpty(innerAlias)) { string keyLeft = mLeft.GetKeyWidthoutAnonymous(); if (base.NavMembers.Contains(keyLeft)) { innerKey = keyLeft; } innerAlias = _ag.GetNavTableAlias(innerKey); } } string alias1 = !string.IsNullOrEmpty(innerAlias) ? innerAlias : _ag.GetTableAlias(innerKey); string alias2 = _ag.GetNavTableAlias(outerKey); builder.AppendNewLine(); builder.Append("LEFT JOIN "); Type type = m.Type; if (type.IsGenericType) { type = type.GetGenericArguments()[0]; } var typeRuntime2 = TypeRuntimeInfoCache.GetRuntimeInfo(type); builder.AppendTable(typeRuntime2.TableSchema, typeRuntime2.TableFullName, typeRuntime2.IsTemporary); builder.Append(" "); builder.Append(alias2); bool withNoLock = !typeRuntime2.IsTemporary && _isNoLock && !string.IsNullOrEmpty(_withNoLock); if (withNoLock) { builder.Append(' '); builder.Append(_withNoLock); } builder.Append(" ON "); for (int i = 0; i < attribute.InnerKeys.Length; i++) { if (attribute.InnerKeys[i].StartsWith(AppConst.CONSTANT_FOREIGNKEY, StringComparison.Ordinal)) { builder.Append(attribute.InnerKeys[i].Substring(7)); } else { builder.Append(alias1); builder.Append('.'); builder.AppendMember(attribute.InnerKeys[i]); } builder.Append(" = "); if (attribute.OuterKeys[i].StartsWith(AppConst.CONSTANT_FOREIGNKEY, StringComparison.Ordinal)) { builder.Append(attribute.OuterKeys[i].Substring(7)); } else { builder.Append(alias2); builder.Append('.'); builder.AppendMember(attribute.OuterKeys[i]); } if (i < attribute.InnerKeys.Length - 1) { builder.Append(" AND "); } } if (nav.Predicate != null) { string alias = _ag.GetNavTableAlias(nav.Key); var visitor = new NavPredicateExpressionVisitor(_ag, builder, alias); visitor.Visit(nav.Predicate); } } }
/// <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, ColumnDescriptorCollection columns = null, int start = 0, int?end = null) { //// specify a new assembly name //var assemblyName = new AssemblyName("Riz.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("Riz.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 dynamicMethod = new DynamicMethod(string.Format("Deserialize{0}", Guid.NewGuid()), typeof(object), new Type[] { typeof(IDataRecord) }, true); //ILGenerator il = methodBuilder.GetILGenerator(); ILGenerator il = dynamicMethod.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.Member; 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) { ColumnDescriptor 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 == AppConst.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) as FieldAccessorBase; if (m == null) { continue; } if (specializedConstructor == null) { il.Emit(OpCodes.Dup); // stack is now [target][target] } // 数据字段类型 Type readerFieldType = reader.GetFieldType(index); Type realReaderFieldType = readerFieldType; // 实体属性类型 Type entityFieldType = m.CLRType; MethodInfo getFieldValue = this.GetReaderMethod(readerFieldType, entityFieldType, ref realReaderFieldType); if (readerFieldType != realReaderFieldType) { readerFieldType = realReaderFieldType; } 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 (entityFieldType == typeof(char) || entityFieldType == typeof(char?)) { il.EmitCall(OpCodes.Call, entityFieldType == 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(entityFieldType); var unboxType = nullUnderlyingType != null && nullUnderlyingType.IsEnum ? nullUnderlyingType : entityFieldType; if (unboxType.IsEnum) { Type numericType = Enum.GetUnderlyingType(unboxType); if (readerFieldType != typeof(string)) { ConvertBoxedStack(il, readerFieldType, 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, entityFieldType); // stack is now [target][target][typed-value] } } else if (entityFieldType.FullName == _linqBinaryName) { var ctor = entityFieldType.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 = readerFieldType == unboxType || readerFieldType == 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 && readerFieldType.IsValueType) { il.Emit(OpCodes.Unbox_Any, readerFieldType); // stack is now [target][target][value] } // not a direct match; need to tweak the unbox ConvertBoxedStack(il, readerFieldType, nullUnderlyingType ?? unboxType, null); } // new Nullable<TValue>(TValue) if (nullUnderlyingType != null) { EmitNewNullable(il, entityFieldType); // 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).Member.GetSetMethod(true); 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 (!entityFieldType.IsValueType) { il.Emit(OpCodes.Ldnull); } else { int localIndex = il.DeclareLocal(entityFieldType).LocalIndex; il.LoadLocalAddress(localIndex); il.Emit(OpCodes.Initobj, entityFieldType); 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>)dynamicMethod.CreateDelegate(typeof(Func <IDataRecord, object>))); }
// 反序列化导航属性 // @prevLine 前一行数据 // @isLine 是否同一行数据<同一父级> void Deserialize_Navigation(object prevModel, object model, string typeName, bool isThisLine) { // CRM_SaleOrder.Client // CRM_SaleOrder.Client.AccountList Type type = model.GetType(); TypeRuntimeInfo typeRuntime = TypeRuntimeInfoCache.GetRuntimeInfo(type); if (string.IsNullOrEmpty(typeName)) { typeName = type.Name; } //foreach (var kvp in _map.Navigations) foreach (var navigation in _map.SelectedNavs) { int start = -1; int end = -1; if (navigation.FieldCount > 0) { start = navigation.StartIndex; end = navigation.StartIndex + navigation.FieldCount; } string keyName = typeName + "." + navigation.Name; if (keyName != navigation.Key) { continue; } var navMember = typeRuntime.GetMember <FieldAccessorBase>(navigation.Name); if (navMember == null) { continue; } Type navType = navMember.CLRType; Func <IDataRecord, object> deserializer = null; TypeRuntimeInfo navTypeRuntime = TypeRuntimeInfoCache.GetRuntimeInfo(navType); object navCollection = null; if (TypeUtils.IsCollectionType(navType)) { // 1:n关系,导航属性为 List<T> navCollection = navMember.Invoke(model); if (navCollection == null) { // new 一个列表类型,如果导航属性定义为接口,则默认使用List<T>来实例化 TypeRuntimeInfo navTypeRuntime2 = navType.IsInterface ? TypeRuntimeInfoCache.GetRuntimeInfo(typeof(List <>).MakeGenericType(navTypeRuntime.GenericArguments[0])) : navTypeRuntime; navCollection = navTypeRuntime2.Constructor.Invoke(); navMember.Invoke(model, navCollection); } } if (!_deserializers.TryGetValue(keyName, out deserializer)) { deserializer = _deserializerImpl.GetTypeDeserializer(navType.IsGenericType ? navTypeRuntime.GenericArguments[0] : navType, _reader, _map.SelectedColumns, start, end); _deserializers[keyName] = deserializer; } // 如果整个导航链中某一个导航属性为空,则跳出递归 object navModel = deserializer(_reader); if (navModel != null) { if (navCollection == null) { // 非集合型导航属性 navMember.Invoke(model, navModel); // // // } else { // 集合型导航属性 if (prevModel != null && isThisLine) { #region 合并列表 // 判断如果属于同一个主表,则合并到上一行的当前明细列表 // 例:CRM_SaleOrder.Client.AccountList string[] keys = keyName.Split('.'); TypeRuntimeInfo curTypeRuntime = TypeRuntimeInfoCache.GetRuntimeInfo(_entityType); Type curType = curTypeRuntime.Type; MemberAccessorBase curAccessor = null; object curModel = prevModel; for (int i = 1; i < keys.Length; i++) { curAccessor = curTypeRuntime.GetMember(keys[i]); curModel = curAccessor.Invoke(curModel); if (curModel == null) { continue; } curType = curModel.GetType(); curTypeRuntime = TypeRuntimeInfoCache.GetRuntimeInfo(curType); // <<<<<<<<<<< 一对多对多关系 >>>>>>>>>> if (curType.IsGenericType && i != keys.Length - 1) { curTypeRuntime = TypeRuntimeInfoCache.GetRuntimeInfo(curType); //if (curTypeRuntime.GenericTypeDefinition == typeof(List<>)) if (TypeUtils.IsCollectionType(curType)) { var member_Count = curTypeRuntime.GetMember("get_Count"); int count = Convert.ToInt32(member_Count.Invoke(curModel)); // List.Count if (count > 0) { var member_Index = curTypeRuntime.GetMember("get_Item"); curModel = member_Index.Invoke(curModel, count - 1); // List[List.Count-1] curTypeRuntime = TypeRuntimeInfoCache.GetRuntimeInfo(curModel.GetType()); } else { // user.Roles.RoleFuncs=>Roles 列表有可能为空 curModel = null; break; } } } } if (curModel != null) { // 如果有两个以上的一对多关系的导航属性,那么在加入列表之前就需要剔除重复的实体 bool isAny = false; if (_map.SelectedNavs.Count > 1) { if (_manyNavigationNumber == null) { _manyNavigationNumber = _map.SelectedNavs.Count(x => HasMany(x.Member)); } if (_manyNavigationNumber != null && _manyNavigationNumber.Value > 1) { if (!_manyNavigationKeys.ContainsKey(keyName)) { _manyNavigationKeys[keyName] = new HashSet <string>(); } curTypeRuntime = TypeRuntimeInfoCache.GetRuntimeInfo(navModel.GetType()); StringBuilder keyBuilder = new StringBuilder(64); foreach (var m in curTypeRuntime.KeyMembers) { var value = m.Invoke(navModel); keyBuilder.AppendFormat("{0}={1};", m.Name, (value ?? string.Empty).ToString()); } string hash = keyBuilder.ToString(); if (_manyNavigationKeys[keyName].Contains(hash)) { isAny = true; } else { _manyNavigationKeys[keyName].Add(hash); } } } if (!isAny) { // 如果列表中不存在,则添加到上一行的相同导航列表中去 var member_Add = navTypeRuntime.GetMember("Add"); member_Add.Invoke(curModel, navModel); } } #endregion } else { // 此时的 navTypeRuntime 是 List<> 类型的运行时 // 先添加 List 列表 var member_Add = navTypeRuntime.GetMember("Add"); member_Add.Invoke(navCollection, navModel); var curTypeRuntime = TypeRuntimeInfoCache.GetRuntimeInfo(navModel.GetType()); StringBuilder keyBuilder = new StringBuilder(64); foreach (var m in curTypeRuntime.KeyMembers) { var value = m.Invoke(navModel); keyBuilder.AppendFormat("{0}={1};", m.Name, (value ?? string.Empty).ToString()); } string hash = keyBuilder.ToString(); if (!_manyNavigationKeys.ContainsKey(keyName)) { _manyNavigationKeys[keyName] = new HashSet <string>(); } if (!_manyNavigationKeys[keyName].Contains(hash)) { _manyNavigationKeys[keyName].Add(hash); } } } if (TypeUtils.IsCollectionType(navTypeRuntime.Type)) { navTypeRuntime = TypeRuntimeInfoCache.GetRuntimeInfo(navTypeRuntime.GenericArguments[0]); } if (navTypeRuntime.NavMembers.Count > 0) { Deserialize_Navigation(prevModel, navModel, keyName, isThisLine); } } } }