/// <summary> /// 判断当前的属性类型是否与已经存在的形成“闭环”。即 /// A.B.A。 当前的最后一个A,此时形成闭环 /// </summary> /// <param name="dicts"></param> /// <param name="current"></param> /// <returns></returns> private bool HasReferenceLoop(Dictionary <int, ReferenceTypeDepthExpression> dicts, ReferenceTypeDepthExpression current) { ReferenceTypeDepthExpression parent = null; if (dicts.TryGetValue(current.ParentKey, out parent) == false) { return(false); } while (parent != null) { if (current.PropertyInfo.PropertyType == parent.PropertyInfo.PropertyType) { return(true); } if (dicts.TryGetValue(parent.ParentKey, out parent) == false) { return(false); } } return(false); }
private void CreateTypeVistor() { ParameterExpression paraExpression = Expression.Parameter(typeof(T), "t"); Tuple <IDictionary <int, ReferenceTypeDepthExpression>, IList <ValueTypeMapping> > selected = RecursiveGetAllSelectedProperties(); IDictionary <int, ReferenceTypeDepthExpression> referenceTypes = selected.Item1; IList <ValueTypeMapping> valueTypes = selected.Item2; #region 首先,根据深度对引用类型进行处理,生成相应的Expression IOrderedEnumerable <ReferenceTypeDepthExpression> values = referenceTypes.Values.OrderBy(t => t.Depth); foreach (ReferenceTypeDepthExpression value in values) { //父节点类型为根类型,即T if (value.ParentKey == 0) { value.Expression = CreatePropertyAccesorExpression(value.PropertyInfo, paraExpression, null); } else { ReferenceTypeDepthExpression parent = null; if ( referenceTypes.TryGetValue(value.ParentKey, out parent) == false) { LogHelper.Logger.Error("failed to get parent ReferenceTypeDepthException."); } value.Expression = CreatePropertyAccesorExpression(value.PropertyInfo, parent.Expression, null); } } #endregion #region 其次,处理所有的值类型或字符串类型,生成相应的访问Func等。 foreach (ValueTypeMapping valueType in valueTypes) { Expression parentExpression = null; //父节点为根类型,即T:typeof(T) if (valueType.ParentKey == 0) { parentExpression = paraExpression; } else { ReferenceTypeDepthExpression parent = null; if ( referenceTypes.TryGetValue(valueType.ParentKey, out parent) == false) { LogHelper.Logger.Error("failed to get parent ReferenceTypeDepthException."); } parentExpression = parent.Expression; } BlockExpression curExpression = CreatePropertyAccesorExpression(valueType.CurrentPropertyInfo, parentExpression, valueType.DbColumnMapping.DefaultValue); m_dbColumnMappings.Add(valueType.DbColumnMapping); Expression <Func <T, object> > lambda = Expression.Lambda <Func <T, Object> >(Expression.Convert(curExpression, typeof(object)), paraExpression); Func <T, object> func = lambda.Compile(); m_properties.Add(valueType.DbColumnMapping.DestColumnOffset, func); } #endregion }
RecursiveGetAllSelectedProperties() { Type stringType = typeof(string); Type type = typeof(T); bool hasMapping = false; #region 递归判断是否有包含DbColumnMapping的值类型或String var pq = new Queue <Type>(); var visitReferenceType = new List <Type>(); pq.Enqueue(type); while (pq.Count > 0) { Type firstType = pq.Dequeue(); PropertyInfo[] props = firstType.GetProperties(); foreach (PropertyInfo prop in props) { if (prop.PropertyType.IsValueType || prop.PropertyType == stringType) { var attrs = (DBColumnMapping[])prop.GetCustomAttributes(typeof(DBColumnMapping), true); bool has = attrs.Any(attr => attr.DestLabel == m_destLabel); if (has == false) { continue; } hasMapping = true; break; } //reference type if (visitReferenceType.Contains(prop.PropertyType) == false) { pq.Enqueue(prop.PropertyType); } } visitReferenceType.Add(firstType); } #endregion //所有的引用类型(不包括string) //key: parentKey:一个利用自增来避免重复的int参数 var referenceDict = new Dictionary <int, ReferenceTypeDepthExpression>(); //所有的值类型 var valueList = new List <ValueTypeMapping>(); #region 读取所有的引用类型、值类型及String类型的属性 int rootKey = 0; int parentKey = 0; var depthQueue = new Queue <Tuple <int, Type, int> >(); depthQueue.Enqueue(new Tuple <int, Type, int>(parentKey++, type, 0)); while (depthQueue.Count > 0) { var firstNode = depthQueue.Dequeue(); int currentKey = firstNode.Item1; Type currentType = firstNode.Item2; int currentDepth = firstNode.Item3; if (currentType.IsAbstract || currentType.IsInterface) { LogHelper.Logger.WarnFormat("getting properties for interface or abstract class type: {0}", currentType); } PropertyInfo[] props = currentType.GetProperties(); foreach (PropertyInfo prop in props) { //值类型或引用类型 if (prop.PropertyType.IsValueType || prop.PropertyType == stringType) { valueList.Add(new ValueTypeMapping(prop, currentKey, currentDepth + 1)); } else { var propTypeDepthException = new ReferenceTypeDepthExpression(prop, currentKey, currentDepth + 1); if (prop.PropertyType == type || HasReferenceLoop(referenceDict, propTypeDepthException)) { LogHelper.Logger.WarnFormat( "there is reference loop(like A.B.C.A) for property type:{0} in declare type:{1}", prop.PropertyType, prop.DeclaringType); continue; } depthQueue.Enqueue(new Tuple <int, Type, int>(parentKey, prop.PropertyType, currentDepth + 1)); referenceDict.Add(parentKey++, propTypeDepthException); } } } #endregion //所有被选取的值类型 IList <ValueTypeMapping> selectedValueList = SelectedValueProperties(valueList, hasMapping); IList <ValueTypeMapping> filteredValueList = FilterValuePropertiesByDbColumn(selectedValueList); return (new Tuple <IDictionary <int, ReferenceTypeDepthExpression>, IList <ValueTypeMapping> >(referenceDict, filteredValueList)); }