/// <summary>
        ///     Adds the item.
        /// </summary>
        /// <param name="index">
        ///     The index.
        /// </param>
        /// <param name="item">
        ///     The item.
        /// </param>
        /// <param name="sourceToTarget">
        ///     if set to <c>true</c> from source to target.
        /// </param>
        private void AddItem(int index, object item, bool sourceToTarget = true)
        {
            ICollectionHandler handler     = sourceToTarget ? this.TargetHandler : this.SourceHandler;
            BindContext        bindContext = sourceToTarget ? this.BindTarget : this.BindSource;
            var list = bindContext.Value as IList;

            bool handled = false;

            if (handler != null)
            {
                handled = handler.AddItem(index, item, bindContext.Source, bindContext.Value);
            }

            if (!handled && list != null)
            {
                IDataGenerator dataGenerator            = sourceToTarget ? this.TargetDataGenerator : this.SourceDataGenerator;
                object         parameter                = sourceToTarget ? this.TargetDataParameter : this.SourceDataParameter;
                Func <object, object, object> generator = sourceToTarget ? this.TargetGenerator : this.SourceGenerator;

                if (dataGenerator != null)
                {
                    list.Insert(index, dataGenerator.Generate(item, parameter));
                }
                else if (generator != null)
                {
                    list.Insert(index, generator(item, parameter));
                }
                else
                {
                    list.Insert(index, item);
                }
            }
        }
Esempio n. 2
0
        public void ResolveReferences(ICollectionHandler handler, IJsonDict item)
        {
            deserializerState            = new DeserializerStateInfo();
            deserializerState.references = new Dictionary <object, IJsonDict>();
            deserializerState.pending    = new Stack <IEnumerable>(handler.GetContainers(item));
            deserializerState.results    = new Dictionary <IJsonDict, object>();

            object referenceId = item.GetValueOrDefault("ref");

            if (referenceId != null)
            {
                deserializerState.references[referenceId] = item;
            }

            IEnumerable enumerable;

            while (deserializerState.pending.Count > 0)
            {
                enumerable = deserializerState.pending.Pop();
                // Debug.Log(string.Format("Processing queued item {0}", idgen.GetId(enumerable, out dummy)));

                var list = enumerable as IJsonList;
                if (list != null)
                {
                    for (int index = 0; index < list.Count; ++index)
                    {
                        if ((item = list[index] as IJsonDict) == null)
                        {
                            continue;                                             // Not an object
                        }
                        if ((item = ResolveItem(item)) == null)
                        {
                            continue;                                      // Replacement not needed
                        }
                        list[index] = item;
                    }
                    continue;
                }
                var dict = enumerable as IJsonDict;
                if (dict != null)
                {
                    foreach (JsonKey kvp in dict)
                    {
                        if ((item = kvp.Value as IJsonDict) == null)
                        {
                            continue;                                           // Not an object
                        }
                        if ((item = ResolveItem(item)) == null)
                        {
                            continue;                                      // Replacement not needed.
                        }
                        dict[kvp.Key] = item;
                    }
                    continue;
                }
                throw new SerializationException(string.Format("Unexpected enumerable of type {0}", enumerable.GetType().FullName));
            }
        }
Esempio n. 3
0
        protected Dictionary <object, ICollectionHandler> references = new Dictionary <object, ICollectionHandler>(); // Collections that we've encountered this pass.

        protected object MakeReference(ICollectionHandler referenced)
        {
            if (referenced.ObjectId == null)
            {
                referenced.ObjectId = serializerState.nextReferenceId++;
            }
            return(new JsonDict {
                { "type", "ref" },
                { "ref", referenced.ObjectId }
            });
        }
Esempio n. 4
0
        public object Deserialize(object input)
        {
            if (input == null)
            {
                throw new SerializationException("Encountered NULL while deserializing input.");
            }
            // Primitives.
            input = Structure.FromPrimitive(input);
            if (input is Structure)
            {
                return((Structure)input);
            }
            IJsonDict dict = input as IJsonDict;

            if (dict == null)
            {
                throw new SerializationException("Deserializing from a " + input.GetType().Name + " is unsupported.");
            }
            // Get the deserializer for this object.
            // This will fail and throw an exception(by design) on unsupported types.
            // "ref" is also considered an unsupported type.  If we see it here, it's either the top-level element
            // (in which case there are no other elements it could possibly be referencing), or we somehow failed
            // to replace it during the reference replacement run.
            TypeHandler        handler = registry.GetDeserializer(GetTypeIdentifier(dict)).CreateHandler(this);
            ICollectionHandler ich     = handler as ICollectionHandler;
            object             result;

            if (ich != null)
            {
                // If we have a collection handler and haven't scanned for backrefs yet, scan for them.
                if (deserializerState == null)
                {
                    ResolveReferences(ich, dict);
                }
                // Is this something we've already resolved?  If so, return that reference.
                result = deserializerState.results.GetValueOrDefault(dict);
                if (result != null)
                {
                    return(result);
                }
            }
            result = handler.ProxyDeserialize(dict);
            if (ich != null)
            {
                deserializerState.results[dict] = result;
            }
            return(result);
        }
Esempio n. 5
0
 protected virtual DataType CreateConfigurationDataType(Type type)
 {
     if (type.IsEnum)
     {
         return(new EnumDataType(type));
     }
     else if (type.IsPrimitive)
     {
         return(new PrimitiveDataType(type));
     }
     else if (type == typeof(string))
     {
         return(new StringDataType());
     }
     else if (type == typeof(DateTime))
     {
         return(new DateTimeDataType());
     }
     else if (type == typeof(TimeSpan))
     {
         return(new TimeSpanDataType());
     }
     else if (type == typeof(FilePath))
     {
         return(new FilePathDataType());
     }
     else if (type == typeof(XmlElement))
     {
         return(new XmlElementDataType());
     }
     else if (DictionaryDataType.IsDictionaryType(type))
     {
         return(new DictionaryDataType(type));
     }
     else
     {
         ICollectionHandler handler = GetCollectionHandler(type);
         if (handler != null)
         {
             return(new CollectionDataType(type, handler));
         }
         else
         {
             return(CreateClassDataType(type));
         }
     }
 }
        /// <summary>
        ///     Removes the item.
        /// </summary>
        /// <param name="index">
        ///     The index.
        /// </param>
        /// <param name="item">
        ///     The item.
        /// </param>
        /// <param name="sourceToTarget">
        ///     if set to <c>true</c> from source to target.
        /// </param>
        private void RemoveItem(int index, object item, bool sourceToTarget = true)
        {
            bool               handled     = false;
            BindContext        bindContext = sourceToTarget ? this.BindTarget : this.BindSource;
            ICollectionHandler handler     = sourceToTarget ? this.TargetHandler : this.SourceHandler;
            var list = bindContext.Value as IList;

            if (handler != null)
            {
                handled = handler.RemoveItem(index, item, bindContext.Source, bindContext.Value);
            }

            if (!handled && list != null)
            {
                list.RemoveAt(index);
            }
        }
        /// <summary>
        ///     Clears the items.
        /// </summary>
        /// <param name="sourceToTarget">
        ///     if set to <c>true</c> from source to target.
        /// </param>
        private void ClearItems(bool sourceToTarget = true)
        {
            BindContext        bindContext = sourceToTarget ? this.BindTarget : this.BindSource;
            ICollectionHandler handler     = sourceToTarget ? this.TargetHandler : this.SourceHandler;
            var list = bindContext.Value as IList;

            bool handled = false;

            if (handler != null)
            {
                handled = handler.Clear(bindContext.Source, bindContext.Value);
            }

            if (!handled && list != null)
            {
                list.Clear();
            }
        }
Esempio n. 8
0
        public object Serialize(object input)
        {
            // If Unity supported a modern C# version with, say, dynamic, we could go back to the overloaded methods approach
            // Instead of this giant mess of if-checks
            if (input is PrimitiveStructure)
            {
                return(((PrimitiveStructure)input).ToPrimitive());
            }
            ICollectionHandler referenced = serializerState.references.GetValueOrDefault(input);

            if (referenced != null)
            {
                return(MakeReference(referenced));
            }
            TypeHandler handler = registry.GetSerializer(input).CreateHandler(this);  // Will throw on unsupported types.

            if (handler is ICollectionHandler)
            {
                // It's important that the reference is set up BEFORE we serialize the handler, otherwise a nested reference to the input may fail to notice
                // the existing reference since we haven't created it yet.
                serializerState.references[input] = (ICollectionHandler)handler;
            }
            return(handler.ProxySerialize(input));
        }
Esempio n. 9
0
 internal CollectionDataType(Type type, ICollectionHandler handler) : base(type)
 {
     this.handler = handler;
 }
Esempio n. 10
0
        void Deserialize(SerializationContext serCtx, object obj, DataCollection itemData, DataItem ukwnDataRoot, string baseName)
        {
            Hashtable expandedCollections = null;

            foreach (DataNode value in itemData)
            {
                ItemProperty prop = (ItemProperty)properties [baseName + value.Name];
                if (prop == null)
                {
                    if (value is DataItem)
                    {
                        DataItem root = new DataItem();
                        root.Name        = value.Name;
                        root.UniqueNames = ((DataItem)value).UniqueNames;
                        if (ukwnDataRoot != null)
                        {
                            ukwnDataRoot.ItemData.Add(root);
                        }
                        Deserialize(serCtx, obj, ((DataItem)value).ItemData, root, baseName + value.Name + "/");

                        // If no unknown data has been added, there is no need to keep this
                        // in the unknown items list.
                        if (ukwnDataRoot != null && !root.HasItemData)
                        {
                            ukwnDataRoot.ItemData.Remove(root);
                        }
                    }
                    else if (obj is IExtendedDataItem && (value.Name != "ctype" || baseName.Length > 0))
                    {
                        // store unreadable raw data to a special property so it can be
                        // serialized back an the original format is kept
                        // The ctype attribute don't need to be stored for the root object, since
                        // it is generated by the serializer
                        ukwnDataRoot.ItemData.Add(value);
                    }
                    continue;
                }
                if (prop.WriteOnly || !prop.CanDeserialize(serCtx, obj))
                {
                    continue;
                }

                try
                {
                    if (prop.ExpandedCollection)
                    {
                        ICollectionHandler handler = prop.ExpandedCollectionHandler;
                        if (expandedCollections == null)
                        {
                            expandedCollections = new Hashtable();
                        }

                        object pos, col;
                        if (!expandedCollections.ContainsKey(prop))
                        {
                            col = handler.CreateCollection(out pos, -1);
                        }
                        else
                        {
                            pos = expandedCollections [prop];
                            col = prop.GetValue(obj);
                        }
                        handler.AddItem(ref col, ref pos, prop.Deserialize(serCtx, obj, value));
                        expandedCollections [prop] = pos;
                        prop.SetValue(obj, col);
                    }
                    else
                    {
                        if (prop.HasSetter && prop.DataType.CanCreateInstance)
                        {
                            prop.SetValue(obj, prop.Deserialize(serCtx, obj, value));
                        }
                        else if (prop.DataType.CanReuseInstance)
                        {
                            object pval = prop.GetValue(obj);
                            if (pval == null)
                            {
                                if (prop.HasSetter)
                                {
                                    throw new InvalidOperationException("The property '" + prop.Name + "' is null and a new instance of '" + prop.PropertyType + "' can't be created.");
                                }
                                else
                                {
                                    throw new InvalidOperationException("The property '" + prop.Name + "' is null and it does not have a setter.");
                                }
                            }
                            prop.Deserialize(serCtx, obj, value, pval);
                        }
                        else
                        {
                            throw new InvalidOperationException("The property does not have a setter.");
                        }
                    }
                }
                catch (Exception ex)
                {
                    throw new InvalidOperationException("Could not set property '" + prop.Name + "' in type '" + Name + "'", ex);
                }
            }
        }
Esempio n. 11
0
        internal DataCollection Serialize(SerializationContext serCtx, object obj)
        {
            DataCollection itemCol = new DataCollection();

            foreach (ItemProperty prop in Properties)
            {
                if (prop.ReadOnly || !prop.CanSerialize(serCtx, obj))
                {
                    continue;
                }
                object val = prop.GetValue(obj);
                if (val == null)
                {
                    continue;
                }
                if (!serCtx.IsDefaultValueSerializationForced(prop) && val.Equals(prop.DefaultValue))
                {
                    continue;
                }

                DataCollection col = itemCol;
                if (prop.IsNested)
                {
                    col = GetNestedCollection(col, prop.NameList, 0);
                }

                if (prop.ExpandedCollection)
                {
                    ICollectionHandler handler = prop.ExpandedCollectionHandler;
                    object             pos     = handler.GetInitialPosition(val);
                    while (handler.MoveNextItem(val, ref pos))
                    {
                        object item = handler.GetCurrentItem(val, pos);
                        if (item == null)
                        {
                            continue;
                        }
                        DataNode data = prop.Serialize(serCtx, obj, item);
                        data.Name = prop.SingleName;
                        col.Add(data);
                    }
                }
                else
                {
                    DataNode data = prop.Serialize(serCtx, obj, val);
                    if (data == null)
                    {
                        continue;
                    }
                    col.Add(data);
                }
            }

            if (obj is IExtendedDataItem)
            {
                // Serialize raw data which could not be deserialized
                DataItem uknData = (DataItem)((IExtendedDataItem)obj).ExtendedProperties ["__raw_data"];
                if (uknData != null)
                {
                    itemCol.Merge(uknData.ItemData);
                }
            }

            return(itemCol);
        }
Esempio n. 12
0
        void AddProperty(object member, string name, Type memberType)
        {
            // Using inherit=false because if a base class already has an ItemProperty applied to the property
            // then that property will already have been added while copying props from the base class.

            object[] ats = Context.AttributeProvider.GetCustomAttributes(member, typeof(Attribute), false);

            ItemPropertyAttribute at = FindPropertyAttribute(ats, "");

            if (at == null)
            {
                return;
            }

            ItemProperty prop = new ItemProperty();

            prop.Name = (at.Name != null) ? at.Name : name;
            prop.ExpandedCollection = Context.AttributeProvider.IsDefined(member, typeof(ExpandedCollectionAttribute), true);
            prop.DefaultValue       = at.DefaultValue;
            prop.IsExternal         = at.IsExternal;
            prop.SkipEmpty          = at.SkipEmpty;
            prop.ReadOnly           = at.ReadOnly;
            prop.WriteOnly          = at.WriteOnly;

            if (prop.ExpandedCollection)
            {
                ICollectionHandler handler = Context.GetCollectionHandler(memberType);
                if (handler == null)
                {
                    throw new InvalidOperationException("ExpandedCollectionAttribute can't be applied to property '" + prop.Name + "' in type '" + ValueType + "' becuase it is not a valid collection.");
                }

                memberType = handler.GetItemType();
                prop.ExpandedCollectionHandler = handler;
            }

            if (at.ValueType != null)
            {
                prop.PropertyType = at.ValueType;
            }
            else
            {
                prop.PropertyType = memberType;
            }

            if (at.SerializationDataType != null)
            {
                try
                {
                    prop.DataType = (DataType)Activator.CreateInstance(at.SerializationDataType, new object[] { prop.PropertyType });
                }
                catch (MissingMethodException ex)
                {
                    throw new InvalidOperationException("Constructor not found for custom data type: " + at.SerializationDataType.Name + " (Type propertyType);", ex);
                }
            }

            if (member is MemberInfo)
            {
                prop.Member = (MemberInfo)member;
                AddProperty(prop);
            }
            else
            {
                prop.InitValue = ((ItemMember)member).InitValue;
                AddProperty(prop, ((ItemMember)member).InsertBefore);
            }

            prop.Initialize(ats, "");

            if (prop.ExpandedCollection && prop.DataType.IsSimpleType)
            {
                throw new InvalidOperationException("ExpandedCollectionAttribute is not allowed in collections of simple types");
            }
        }
 /// <summary>
 ///     Sets the source collection handler.
 /// </summary>
 /// <param name="handler">
 ///     The handler.
 /// </param>
 /// <returns>
 ///     The <see cref="WeakCollectionBinding"/>.
 /// </returns>
 public WeakCollectionBinding SetSourceCollectionHandler(ICollectionHandler handler)
 {
     this.SourceHandler = handler;
     return(this);
 }
 /// <summary>
 ///     Sets the target collection handler.
 /// </summary>
 /// <param name="handler">
 ///     The handler.
 /// </param>
 /// <returns>
 ///     The <see cref="WeakCollectionBinding"/>.
 /// </returns>
 public WeakCollectionBinding SetTargetCollectionHandler(ICollectionHandler handler)
 {
     this.TargetHandler = handler;
     return(this);
 }
 internal CollectionDataType(Type type, ICollectionHandler handler)
     : base(type)
 {
     this.handler = handler;
 }