Ejemplo n.º 1
0
        /// <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);
        }
Ejemplo n.º 2
0
        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
        }
Ejemplo n.º 3
0
        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));
        }