Beispiel #1
0
        /// <summary>
        /// Secondary entry point for all object representations. Called primarily by
        /// <see cref="Prepare(object,bool)"/>, but also recursively when preparing interactive
        /// reflected objects, etc. to prepare child member values.
        /// </summary>
        /// <param name="representations">The representations already produced for this object.</param>
        /// <param name="depth">The current object graph depth.</param>
        /// <param name="obj">The current object to represent.</param>
        internal void Prepare(RepresentedObject representations, int depth, object obj)
        {
            if (obj == null)
            {
                return;
            }

            MainThread.Ensure();

            var normalizedObj = Normalize(obj);

            representations.Add(normalizedObj);

            if (normalizedObj == null)
            {
                representations.Add(ToJson(obj));
            }
            else
            {
                representations.Add(ToJson(normalizedObj));
            }

            var skipInteractive = false;
            var interactiveObj  = obj;

            // It is not safe to provide Representation objects to providers
            // which can cause a stack overflow in Normalize if the provider
            // decides to directly pack the provied Representation object in
            // another Representation object for whatever reason.
            if (obj is Representation)
            {
                obj = ((Representation)obj).Value;
            }

            foreach (var provider in providers)
            {
                try {
                    foreach (var representation in provider.ProvideRepresentations(obj))
                    {
                        representations.Add(Normalize(representation));
                        skipInteractive |= representation
                                           is InteractiveObject.GetMemberValueError;
                    }
                } catch (Exception e) {
                    Log.Error(TAG, $"provider {provider}.ProvideRepresentation", e);
                }
            }

            if (skipInteractive)
            {
                return;
            }

            foreach (var interactiveObject in PrepareInteractiveObjects(depth, interactiveObj))
            {
                interactiveObject.Handle = ObjectCache.Shared.GetHandle(interactiveObject);
                interactiveObject.Initialize();
                representations.Add(interactiveObject);
            }
        }
Beispiel #2
0
        void SafeReadMembers()
        {
            var propertyNames = new HashSet <string> ();
            var members       = new List <Tuple <RepresentedMemberInfo, object> > ();

            for (var type = RepresentedType; type != null; type = type.BaseType)
            {
                foreach (var memberItem in type.ProxyableMembers)
                {
                    var pi = memberItem.Value.ResolvedMemberInfo as PropertyInfo;
                    if (pi != null)
                    {
                        if (propertyNames.Contains(pi.Name))
                        {
                            continue;
                        }

                        propertyNames.Add(pi.Name);
                    }

                    object value;
                    try {
                        if (memberFilter != null &&
                            !memberFilter(memberItem.Value, representedObject))
                        {
                            value = new GetMemberValueError();
                        }
                        else
                        {
                            value = memberItem.Value.GetValue(representedObject);
                        }
                    } catch (TargetInvocationException e) {
                        value = new GetMemberValueError(e.InnerException);
                    } catch (Exception e) {
                        value = new GetMemberValueError(e);
                    }

                    var preparedValue = new RepresentedObject(value?.GetType());
                    ItemPreparer(preparedValue, Depth + 1, value);
                    if (preparedValue.Count == 0)
                    {
                        preparedValue = null;
                    }

                    members.Add(Tuple.Create(memberItem.Value, (object)preparedValue));
                }
            }

            members.Sort((x, y) => string.Compare(x.Item1.Name, y.Item1.Name));

            Members = new RepresentedMemberInfo [members.Count];
            Values  = new object [members.Count];

            for (int i = 0; i < members.Count; i++)
            {
                Members [i] = members [i].Item1;
                Values [i]  = members [i].Item2;
            }
        }
        protected override IInteractiveObject Interact(bool isUserInteraction, object message)
        {
            if (!isUserInteraction && Depth > 0)
            {
                return(this);
            }

            if (slice == null)
            {
                slice = new object [defaultSliceSize];
            }

            int i = 0;

            while (i < slice.Length)
            {
                // In case of error, default to true so we can show "cannot evaluate"
                var    enumerated = true;
                object current    = null;

                try {
                    enumerated = enumerator.MoveNext();
                    if (enumerated)
                    {
                        current = enumerator.Current;
                    }
                } catch (Exception e) {
                    Log.Error(TAG, e);
                    current = new InteractiveObject.GetMemberValueError(e);
                }

                if (!enumerated)
                {
                    IsLastSlice = true;
                    break;
                }

                var result = new RepresentedObject(current?.GetType());
                ItemPreparer(result, Depth + 1, current);
                if (result.Count == 0)
                {
                    result = null;
                }

                slice [i++] = result;
            }

            if (i < slice.Length)
            {
                Array.Resize(ref slice, i);
            }

            return(this);
        }
        protected override void ReadMembers()
        {
            Members = new RepresentedMemberInfo [values.Count];
            Values  = new object [values.Count];

            for (int i = 0; i < values.Count; i++)
            {
                var entry = values [i];

                var value = new RepresentedObject(entry.Item2?.GetType());
                ItemPreparer(value, Depth + 1, entry.Item2);
                if (value.Count == 0)
                {
                    value = null;
                }

                Members [i] = entry.Item1;
                Values [i]  = value;
            }
        }
Beispiel #5
0
        /// <summary>
        /// Prepare serializable representations for an arbitrary object.
        /// </summary>
        public RepresentedObject Prepare(object obj, bool allowISerializableObject = true)
        {
            if (obj == null)
            {
                return(null);
            }

            MainThread.Ensure();

            currentPreparePassAllowsISerializableObject = allowISerializableObject;

            var representations = new RepresentedObject(obj.GetType());

            Prepare(representations, 0, obj);
            if (representations.Count == 0)
            {
                return(null);
            }

            return(representations);
        }