Ejemplo n.º 1
0
        private ReferenceContext(string segment, ReferenceContext parent, TableStore store, ClassMapping cMapping)
        {
            Store    = store;
            CMapping = cMapping;

            //init lists
            Children      = new List <ReferenceContext>();
            ParentContext = parent;

            //try to extract TypeOf part of the path
            var parts = segment.Split('\\');

            segment = parts[0];
            var typeHint = parts.Length > 1 ? parts[1] : null;

            Segment = segment;

            //set up path type hint if it is defined
            if (!string.IsNullOrWhiteSpace(typeHint))
            {
                PathTypeHint = Store.MetaData.ExpressType(typeHint.ToUpper());
            }

            if (segment == "parent")
            {
                PathTypeHint = Store.MetaData.ExpressType(CMapping.ParentClass.ToUpper());
                ContextType  = ReferenceContextType.Parent;
                return;
            }

            Index        = TableStore.GetPropertyIndex(ref segment);
            PropertyInfo = Store.GetPropertyInfo(segment, parent.SegmentType, Index);
            MetaProperty = Store.GetProperty(parent.SegmentType, segment);
            var info = PropertyInfo != null
                    ? PropertyInfo.PropertyType
                    : (MetaProperty != null
                        ? MetaProperty.EnumerableType ?? MetaProperty.PropertyInfo.PropertyType
                        : null);

            if (info == null)
            {
                Store.Log.WriteLine("Type {0} doesn't have a property {1}.", parent.PathTypeHint.ExpressName, segment);
                return;
            }

            PropertyTypeHint = Store.MetaData.ExpressType(MetaProperty != null ?
                                                          MetaProperty.EnumerableType ?? MetaProperty.PropertyInfo.PropertyType :
                                                          (PropertyInfo != null ? PropertyInfo.PropertyType : null)
                                                          );


            //set up type of the context
            var isEnumerable = MetaProperty != null && MetaProperty.EnumerableType != null;

            if (isEnumerable)
            {
                if (MetaProperty.EnumerableType.IsValueType ||
                    MetaProperty.EnumerableType == typeof(string) ||
                    typeof(IExpressValueType).IsAssignableFrom(MetaProperty.EnumerableType))
                {
                    ContextType = ReferenceContextType.ScalarList;
                }
                else
                {
                    ContextType = ReferenceContextType.EntityList;
                }
            }
            else
            {
                if (info.IsValueType ||
                    info == typeof(string) ||
                    typeof(IExpressValueType).IsAssignableFrom(info))
                {
                    ContextType = ReferenceContextType.Scalar;
                }
                else
                {
                    ContextType = ReferenceContextType.Entity;
                }
            }
        }
Ejemplo n.º 2
0
        private void AddToPath(ReferenceContext targetContext, IPersistEntity parent, IPersistEntity child)
        {
            //get context path from root entity
            var ctxStack    = new Stack <ReferenceContext>();
            var entityStack = new Stack <IPersistEntity>();
            var context     = targetContext;

            while (!context.IsRoot && context.ContextType != ReferenceContextType.Parent)
            {
                ctxStack.Push(context);
                context = context.ParentContext;
            }

            var entity = parent;

            while (ctxStack.Count != 0)
            {
                context = ctxStack.Pop();
                entityStack.Push(entity);
                //browse to the level of the bottom context and call ResolveContext there
                var index = context.Index != null ? new[] { context.Index } : null;
                var value = context.PropertyInfo.GetValue(entity, index);
                if (context.ContextType == ReferenceContextType.Entity)
                {
                    var e = value as IPersistEntity;
                    //if it is null, create a new one or assign the child
                    if (e == null)
                    {
                        e = context == targetContext ? child : Store.ResolveContext(context, -1, true);
                        Store.AssignEntity(entity, e, context);
                        entity = e;
                        continue;
                    }

                    //verify that this is the desired one by the values. If not, create a new one on this level and higher
                    if (TableStore.IsValidEntity(context, e))
                    {
                        entity = e;
                        continue;
                    }

                    //create a new one and assign it higher
                    e = context == targetContext ? child : Store.ResolveContext(context, -1, true);
                    Join(e, context, entityStack);
                    entity = e;
                    continue;
                }

                //it should be enumerable
                var entities = value as IEnumerable;
                if (entities == null)
                {
                    Store.Log.WriteLine("It wasn't possible to browse to the data entry point.");
                    return;
                }

                if (context == targetContext)
                {
                    Store.AssignEntity(entity, child, context);
                    return;
                }

                //get first valid entity
                entity = GetFirstValid(entities.Cast <object>(), context);
                //entity = entities.Cast<object>().FirstOrDefault(e => TableStore.IsValidEntity(context, e)) as IPersistEntity;
                if (entity != null)
                {
                    continue;
                }

                //create new entity and assign it on a higher level
                entity = Store.ResolveContext(context, -1, true);
                AddToPath(context, parent, entity);
            }
        }