internal static XIdentifierBox Box <TType, TId>(XIdentifier <TType, TId> identifier)
     where TType : class =>
 new XIdentifierBox(identifier)
 {
     Type         = typeof(TType),
     IdType       = typeof(TId),
     getId        = (obj) => identifier.GetId((TType)obj),
     canId        = (type) => identifier.CanId(type),
     defaultValue = ReflectionTools.GetDefaultValue(typeof(TId)),
     equals       = (x, y) => identifier.Equals((TType)x, (TType)y),
     hashCode     = (obj) => identifier.GetHashCode((TType)obj),
     keyEquals    = (x, y) => identifier.KeyComparer.Equals((TId)x, (TId)y),
     keyHash      = (obj) => identifier.KeyComparer.GetHashCode((TId)obj)
 };
Example #2
0
        protected override bool OnRead <T>(IXReadOperation reader, XType <T> xType, XElement element, Func <object, bool> assign,
                                           XObjectArgs args)
        {
            Type type = typeof(T);

            // A serialized reference has no attributes, no elements, some text, is of a type that can be ID'd,
            // and not of a type that has a registered XTexter

            string value = element.Value;

            if (!element.HasAttributes &&
                !element.HasElements &&
                !string.IsNullOrEmpty(value) &&
                xType.Component <XTexter <T> >() == null &&
                Identifier.CanId(type, out Type idType))
            {
                bool   idFound = false;
                object id      = null;

                reader.Read(element, idType, x =>
                {
                    idFound = true;
                    if (!Identifier.KeyComparer.Equals(x, ReflectionTools.GetDefaultValue(idType)))
                    {
                        id = x;
                    }
                    return(true);
                },
                            XObjectArgs.DefaultIgnoreElementName);

                // Schedule a task to assign the object if it shows up in the dictionary

                reader.AddTask(this, () =>
                {
                    if (!idFound)
                    {
                        return(false);
                    }
                    if (id == null)
                    {
                        return(true);
                    }
                    if (referenceObjects.TryGetValue(id, out object refObject))
                    {
                        if (refObject == null || type == refObject.GetType())
                        {
                            return(assign(refObject));
                        }
                        else
                        {
                            throw new InvalidOperationException(
                                $"Possible collision: the reference object with ID {id} was of expected type {type.Name}, " +
                                $"but that ID resolved to an object of type {refObject.GetType().Name}.");
                        }
                    }

                    return(false);
                });

                return(true);
            }

            return(false);
        }