// 获取成员包装器的外键特性 private ForeignKeyAttribute GetForeignKeyAttribute(FieldAccessorBase m, string memberName) { if (m == null) { throw new XFrameworkException("Member {0}.{1} not found.", _type.Name, memberName); } var attribute = m.GetCustomAttribute <ForeignKeyAttribute>(); if (attribute == null) { // 如果是属性,要求标记为 virtual var property = m as PropertyAccessor; if (property != null) { var getMethod = property.Member.GetGetMethod(true); if (getMethod != null && !getMethod.IsVirtual) { return(null); } } // 区分一对一和一对多导航属性 var navEntityType = m.CLRType.IsGenericType ? m.CLRType.GetGenericArguments()[0] : m.CLRType; var navTypeRuntime = TypeRuntimeInfoCache.GetRuntimeInfo(navEntityType); if (TypeUtils.IsCollectionType(m.CLRType)) { // 1:n 关系,外键实体必须持有当前实体的所有主键属性 int index = 0; string[] innerKeys = null; string[] outerKeys = null; foreach (FieldAccessorBase inner in this.KeyMembers) { if (!navTypeRuntime.Members.Contains(inner.Name)) { innerKeys = null; outerKeys = null; break; } else { var outer = navTypeRuntime.GetMember <FieldAccessorBase>(inner.Name); if (outer == null) { innerKeys = null; outerKeys = null; break; } else { if (innerKeys == null) { innerKeys = new string[this.KeyMembers.Count]; } if (outerKeys == null) { outerKeys = new string[this.KeyMembers.Count]; } innerKeys[index] = inner.Column != null && !string.IsNullOrEmpty(inner.Column.Name) ? inner.Column.Name : inner.Name; outerKeys[index] = inner.Column != null && !string.IsNullOrEmpty(inner.Column.Name) ? inner.Column.Name : inner.Name; } } index += 1; } if (innerKeys != null) { attribute = new ForeignKeyAttribute(innerKeys, outerKeys); } } else { // 1:1 关系,分两种情况 // 1. 当前实体持有外键实体的主键属性 // 2. 外键实体持有当前实体的主键属性 if (navTypeRuntime.KeyMembers.Count > 0) { int index = 0; string[] innerKeys = null; string[] outerKeys = null; foreach (FieldAccessorBase outer in navTypeRuntime.KeyMembers) { if (!this.Members.Contains(outer.Name)) { innerKeys = null; outerKeys = null; break; } else { var inner = this.GetMember <FieldAccessorBase>(outer.Name); if (inner == null) { innerKeys = null; outerKeys = null; break; } else { if (innerKeys == null) { innerKeys = new string[navTypeRuntime.KeyMembers.Count]; } if (outerKeys == null) { outerKeys = new string[navTypeRuntime.KeyMembers.Count]; } innerKeys[index] = inner.Column != null && !string.IsNullOrEmpty(inner.Column.Name) ? inner.Column.Name : inner.Name; outerKeys[index] = outer.Column != null && !string.IsNullOrEmpty(outer.Column.Name) ? outer.Column.Name : outer.Name; } } index += 1; } if (innerKeys != null) { attribute = new ForeignKeyAttribute(innerKeys, outerKeys); } } if (attribute == null) { int index = 0; string[] innerKeys = null; string[] outerKeys = null; foreach (FieldAccessorBase inner in this.KeyMembers) { if (!navTypeRuntime.Members.Contains(inner.Name)) { innerKeys = null; outerKeys = null; break; } else { var outer = navTypeRuntime.GetMember <FieldAccessorBase>(inner.Name); if (outer == null) { innerKeys = null; outerKeys = null; break; } else { if (innerKeys == null) { innerKeys = new string[this.KeyMembers.Count]; } if (outerKeys == null) { outerKeys = new string[this.KeyMembers.Count]; } innerKeys[index] = inner.Column != null && !string.IsNullOrEmpty(inner.Column.Name) ? inner.Column.Name : inner.Name; outerKeys[index] = inner.Column != null && !string.IsNullOrEmpty(inner.Column.Name) ? inner.Column.Name : inner.Name; } } index += 1; } if (innerKeys != null) { attribute = new ForeignKeyAttribute(innerKeys, outerKeys); } } } } return(attribute); }
/// <summary> /// 获取当前类型的所有成员 /// </summary> protected virtual IEnumerable <MemberInfo> GetTypeMembers(Type type, bool @private) { return(TypeUtils.GetMembers(type, @private)); }
/// <summary> /// 将 <see cref="IDataRecord"/> 上的当前行反序列化为实体 /// </summary> /// <param name="prevModel">前一行数据</param> /// <param name="isThisLine">是否同一行数据</param> /// <returns></returns> internal object Deserialize(object prevModel, out bool isThisLine) { isThisLine = false; #region 基元类型 if (_isPrimitive == null) { _isPrimitive = TypeUtils.IsPrimitiveType(_entityType) || _reader.GetName(0) == AppConst.AUTO_INCREMENT_NAME; } if (_isPrimitive.Value) { if (_reader.IsDBNull(0)) { return(TypeUtils.GetNullValue(_entityType)); //default(T); } var obj = _reader.GetValue(0); if (obj.GetType() != _entityType) { // fix#Nullable<T> issue if (!_entityType.IsGenericType) { obj = Convert.ChangeType(obj, _entityType); } else { Type type2 = _entityType.GetGenericTypeDefinition(); if (type2 != typeof(Nullable <>)) { throw new NotSupportedException(string.Format("type {0} not suppored.", type2.FullName)); } obj = Convert.ChangeType(obj, Nullable.GetUnderlyingType(_entityType)); } } return(obj); } #endregion #region 动态类型 if (_isDynamic) { ExpandoObject obj = new ExpandoObject(); var result = ((IDictionary <string, object>)obj); for (int i = 0; i < _reader.FieldCount; i++) { var value = _reader.GetValue(i); if (value == DBNull.Value) { value = null; } result.Add(_reader.GetName(i), value); } return((dynamic)obj); } #endregion #region 实体类型 object model = null; if (_map == null || _map.SelectedNavs == null || _map.SelectedNavs.Count == 0) { // 没有字段映射说明或者没有导航属性 if (_entityDeserializer == null) { _entityDeserializer = _deserializerImpl.GetTypeDeserializer(_entityType, _reader, _map != null ? _map.SelectedColumns : null, 0); } model = _entityDeserializer(_reader); } else { // 第一层 if (_entityDeserializer == null) { _entityDeserializer = _deserializerImpl.GetTypeDeserializer(_entityType, _reader, _map.SelectedColumns, 0, _map.SelectedNavs.MinIndex); } model = _entityDeserializer(_reader); // 若有 1:n 的导航属性,判断当前行数据与上一行数据是否相同 if (prevModel != null && _map.HasMany) { isThisLine = true; foreach (var m in _typeRuntime.KeyMembers) { var value1 = m.Invoke(prevModel); var value2 = m.Invoke(model); isThisLine = isThisLine && value1.Equals(value2); if (!isThisLine) { // Fix issue#换行时清空上一行的导航键缓存 _manyNavigationKeys.Clear(); break; } } } // 递归导航属性 this.Deserialize_Navigation(isThisLine ? prevModel : null, model, string.Empty, isThisLine); } return(model); #endregion }
/// <summary> /// 初始化 <see cref="TypeRuntimeInfo"/> 类的新实例 /// </summary> /// <param name="type">类型声明</param> /// <param name="includePrivates">包含私有成员</param> internal TypeRuntimeInfo(Type type, bool includePrivates) { _type = type; _isAnonymousType = TypeUtils.IsAnonymousType(_type); _includePrivates = includePrivates; }
// 反序列化导航属性 // @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); } } } }