public void ClassWithAnonymousType_HasPropertyBagGenerated()
        {
            // Check properties are generated for anonymous field types.
            {
                var propertyBag = PropertyBagStore.GetPropertyBag(typeof(ClassWithAnonymousType));

                Assert.That(propertyBag, Is.InstanceOf(typeof(ContainerPropertyBag <ClassWithAnonymousType>)));

                var typed      = propertyBag as ContainerPropertyBag <ClassWithAnonymousType>;
                var container  = default(ClassWithAnonymousType);
                var properties = typed.GetProperties(ref container);

                Assert.That(properties.Count(), Is.EqualTo(1));
                Assert.That(properties.ElementAt(0), Is.InstanceOf(typeof(Property <ClassWithAnonymousType, (int IntValue, float FloatValue)>)));
            }

            // Check that the anonymous type has a property bag generated
            {
                var propertyBag = PropertyBagStore.GetPropertyBag(typeof((int IntValue, float FloatValue)));
                Assert.That(propertyBag, Is.InstanceOf(typeof(ContainerPropertyBag <(int IntValue, float FloatValue)>)));

                var typed      = propertyBag as ContainerPropertyBag <(int IntValue, float FloatValue)>;
                var container  = default((int IntValue, float FloatValue));
                var properties = typed.GetProperties(ref container);

                Assert.That(properties.Count(), Is.EqualTo(2));
                Assert.That(properties.ElementAt(0), Is.InstanceOf(typeof(Property <(int IntValue, float FloatValue), int>)));
                Assert.That(properties.ElementAt(1), Is.InstanceOf(typeof(Property <(int IntValue, float FloatValue), float>)));
            }
        }
        public void ClassWithPointerTypes_HasHasPropertyBagGenerated()
        {
            var propertyBag = PropertyBagStore.GetPropertyBag(typeof(ClassWithPointerTypes)) as ContainerPropertyBag <ClassWithPointerTypes>;

            Assert.That(propertyBag, Is.Not.Null);
            Assert.That(propertyBag.GetProperties().Count(), Is.EqualTo(1));
        }
Example #3
0
        /// <summary>
        /// Determines whether two object instances are equal using a deep comparison.
        /// </summary>
        /// <param name="lhs">The first object to compare.</param>
        /// <param name="rhs">The second object to compare.</param>
        /// <returns><see langword="true"/> if the objects are considered equal; otherwise, <see langword="false"/>.</returns>
        public bool CompareEqual(object lhs, object rhs)
        {
            if (lhs == null)
            {
                return(rhs == null);
            }
            if (rhs == null)
            {
                return(false);
            }

            var type = lhs.GetType();

#if !UNITY_DOTSPLAYER
            if (typeof(UnityEngine.Object).IsAssignableFrom(type))
            {
                return(lhs.Equals(rhs));
            }
#endif
            var properties = PropertyBagStore.GetPropertyBag(type);

            if (null == properties)
            {
                throw new MissingPropertyBagException(type);
            }

            m_References?.Clear();
            m_LhsObject = lhs;
            m_RhsObject = rhs;
            m_Equals    = true;

            m_Stack = rhs;
            properties.Accept(this, ref lhs);
            return(m_Equals);
        }
        public void ClassThatInheritsClassWithAttributes_HasPropertyBagGenerated()
        {
            var container  = default(SuperClassWithAttributeOnPrivateField);
            var properties = (PropertyBagStore.GetPropertyBag(typeof(SuperClassWithAttributeOnPrivateField)) as IPropertyBag <SuperClassWithAttributeOnPrivateField>).GetProperties(ref container);

            Assert.That(properties.Count(), Is.EqualTo(1));
            Assert.That(properties.First().HasAttribute <CustomAttribute>());
        }
Example #5
0
        /// <summary>
        /// Creates and registers a <see cref="IPropertyBag{T}"/> for a <see cref="Dictionary{TKey, TValue}"/> type.
        /// </summary>
        /// <remarks>
        /// The container is required to provide AOT code paths for <see cref="PropertyVisitor"/>.
        /// </remarks>
        /// <typeparam name="TContainer">The container type to register.</typeparam>
        /// <typeparam name="TKey">The key type to register.</typeparam>
        /// <typeparam name="TValue">The value type to register.</typeparam>
        public static void RegisterDictionary <TContainer, TKey, TValue>()
        {
            AOT.DictionaryPropertyGenerator <TContainer, Dictionary <TKey, TValue>, TKey, TValue> .Preserve();

            if (PropertyBagStore.TypedStore <IPropertyBag <Dictionary <TKey, TValue> > > .PropertyBag == null)
            {
                PropertyBagStore.AddPropertyBag(new DictionaryPropertyBag <TKey, TValue>());
            }
        }
Example #6
0
        /// <summary>
        /// Creates and registers a <see cref="IPropertyBag{T}"/> for a built in array type.
        /// </summary>
        /// <remarks>
        /// The container is required to provide AOT code paths for <see cref="PropertyVisitor"/>.
        /// </remarks>
        /// <typeparam name="TContainer">The container type to register.</typeparam>
        /// <typeparam name="TElement">The element type to register.</typeparam>
        public static void RegisterArray <TContainer, TElement>()
        {
            AOT.ListPropertyGenerator <TContainer, TElement[], TElement> .Preserve();

            if (PropertyBagStore.TypedStore <IPropertyBag <TElement[]> > .PropertyBag == null)
            {
                PropertyBagStore.AddPropertyBag(new ArrayPropertyBag <TElement>());
            }
        }
Example #7
0
        public void ClassWithMultidimensionalGeneric_HasPropertyBagGenerated()
        {
            var propertyBag = PropertyBagStore.GetPropertyBag(typeof(ClassWithMultidimensionalGeneric)) as ContainerPropertyBag <ClassWithMultidimensionalGeneric>;

            Assert.That(propertyBag, Is.Not.Null);
            var container = new ClassWithMultidimensionalGeneric();

            Assert.That(propertyBag.GetProperties(ref container).Count(), Is.EqualTo(0));
        }
        /// <summary>
        /// Tries to visit the specified <paramref name="container"/> by ref using the specified <paramref name="visitor"/>.
        /// </summary>
        /// <param name="visitor">The visitor.</param>
        /// <param name="container">The container to visit.</param>
        /// <param name="errorCode">When this method returns, contains the error code.</param>
        /// <typeparam name="TContainer">The declared container type.</typeparam>
        /// <returns><see langword="true"/> if the visitation succeeded; <see langword="false"/> otherwise.</returns>
        public static bool TryAccept <TContainer>(IPropertyBagVisitor visitor, ref TContainer container, out VisitErrorCode errorCode)
        {
            if (!RuntimeTypeInfoCache <TContainer> .IsContainerType)
            {
                errorCode = VisitErrorCode.InvalidContainerType;
                return(false);
            }

            // Can not visit a null container.
            if (RuntimeTypeInfoCache <TContainer> .CanBeNull)
            {
                if (EqualityComparer <TContainer> .Default.Equals(container, default))
                {
                    errorCode = VisitErrorCode.NullContainer;
                    return(false);
                }
            }

            if (!RuntimeTypeInfoCache <TContainer> .IsValueType && typeof(TContainer) != container.GetType())
            {
                if (!RuntimeTypeInfoCache.IsContainerType(container.GetType()))
                {
                    errorCode = VisitErrorCode.InvalidContainerType;
                    return(false);
                }

                var properties = PropertyBagStore.GetPropertyBag(container.GetType());

                if (null == properties)
                {
                    errorCode = VisitErrorCode.MissingPropertyBag;
                    return(false);
                }

                // At this point the generic parameter is useless to us since it's not the correct type.
                // Instead we need to retrieve the untyped property bag and accept on that. Since we don't know the type
                // We need to box the container and let the property bag cast it internally.
                var boxed = (object)container;
                properties.Accept(visitor, ref boxed);
                container = (TContainer)boxed;
            }
            else
            {
                var properties = PropertyBagStore.GetPropertyBag <TContainer>();

                if (null == properties)
                {
                    errorCode = VisitErrorCode.MissingPropertyBag;
                    return(false);
                }

                PropertyBag.AcceptWithSpecializedVisitor(properties, visitor, ref container);
            }

            errorCode = VisitErrorCode.Ok;
            return(true);
        }
        public PropertyWrapper(T value)
        {
            if (!PropertyBagStore.Exists <PropertyWrapper <T> >())
            {
                PropertyBagStore.AddPropertyBag(new PropertyBag());
            }

            Value = value;
        }
Example #10
0
        /// <summary>
        /// Creates and registers a <see cref="IPropertyBag{T}"/> for a <see cref="HashSet{TElement}"/> type.
        /// </summary>
        /// <remarks>
        /// The container is required to provide AOT code paths for <see cref="PropertyVisitor"/>.
        /// </remarks>
        /// <typeparam name="TContainer">The container type to register.</typeparam>
        /// <typeparam name="TElement">The element type to register.</typeparam>
        public static void RegisterHashSet <TContainer, TElement>()
        {
            AOT.SetPropertyGenerator <TContainer, HashSet <TElement>, TElement> .Preserve();

            if (PropertyBagStore.TypedStore <IPropertyBag <HashSet <TElement> > > .PropertyBag == null)
            {
                PropertyBagStore.AddPropertyBag(new HashSetPropertyBag <TElement>());
            }
        }
Example #11
0
        static void Initialize()
        {
            if (s_Registered)
            {
                return;
            }

            s_Registered = true;
            PropertyBagStore.RegisterProvider(new ReflectedPropertyBagProvider());
        }
Example #12
0
        /// <summary>
        /// Registers an internal list property bag for the given types.
        /// </summary>
        /// <typeparam name="TContainer">The container type to register.</typeparam>
        /// <typeparam name="TSet">The generic set type to register.</typeparam>
        /// <typeparam name="TElement">The element type to register.</typeparam>
        public static void RegisterSet <TContainer, TSet, TElement>()
            where TSet : ISet <TElement>
        {
            AOT.SetPropertyGenerator <TContainer, TSet, TElement> .Preserve();

            if (PropertyBagStore.TypedStore <IPropertyBag <TSet> > .PropertyBag == null)
            {
                PropertyBagStore.AddPropertyBag(new SetPropertyBag <TSet, TElement>());
            }
        }
Example #13
0
        /// <summary>
        /// Registers an internal list property bag for the given types.
        /// </summary>
        /// <typeparam name="TContainer">The container type to register.</typeparam>
        /// <typeparam name="TList">The generic list type to register.</typeparam>
        /// <typeparam name="TElement">The element type to register.</typeparam>
        public static void RegisterList <TContainer, TList, TElement>()
            where TList : IList <TElement>
        {
            AOT.ListPropertyGenerator <TContainer, TList, TElement> .Preserve();

            if (PropertyBagStore.TypedStore <IPropertyBag <TList> > .PropertyBag == null)
            {
                PropertyBagStore.AddPropertyBag(new ListPropertyBag <TList, TElement>());
            }
        }
Example #14
0
 static void Initialize()
 {
     PropertyBagStore.AddPropertyBag(new AnimationCurvePropertyBag());
     PropertyBagStore.AddPropertyBag(new KeyFramePropertyBag());
     PropertyBagStore.AddPropertyBag(new Vector2IntPropertyBag());
     PropertyBagStore.AddPropertyBag(new Vector3IntPropertyBag());
     PropertyBagStore.AddPropertyBag(new RectPropertyBag());
     PropertyBagStore.AddPropertyBag(new RectIntPropertyBag());
     PropertyBagStore.AddPropertyBag(new BoundsPropertyBag());
     PropertyBagStore.AddPropertyBag(new BoundsIntPropertyBag());
 }
        public void ClassWithMultidimensionalGeneric_HasPropertyBagGenerated()
        {
            var propertyBag = PropertyBagStore.GetPropertyBag(typeof(ClassWithMultidimensionalGeneric)) as ContainerPropertyBag <ClassWithMultidimensionalGeneric>;

            Assert.That(propertyBag, Is.Not.Null);
            var container = new ClassWithMultidimensionalGeneric();

            // @TODO ILPP should support this case
            // Assert.That(propertyBag.GetProperties(ref container).Count(), Is.EqualTo(2));
            Assert.Pass(); // Test is inconclusive on CI
        }
        /// <summary>
        /// Constructs a new instance of the given <see cref="TContainer"/> type.
        /// </summary>
        /// <typeparam name="TContainer">The container type to construct.</typeparam>
        /// <returns>A new instance of <see cref="TContainer"/>.</returns>
        public static TContainer CreateInstance <TContainer>()
        {
            var propertyBag = PropertyBagStore.GetPropertyBag <TContainer>();

            if (null == propertyBag)
            {
                throw new MissingPropertyBagException(typeof(TContainer));
            }

            return(propertyBag.CreateInstance());
        }
Example #17
0
        /// <summary>
        /// Registers an internal dictionary property bag for the given types.
        /// </summary>
        /// <typeparam name="TContainer">The container type to register.</typeparam>
        /// <typeparam name="TDictionary">The generic dictionary type to register.</typeparam>
        /// <typeparam name="TKey">The key type to register.</typeparam>
        /// <typeparam name="TValue">The value type to register.</typeparam>
        public static void RegisterDictionary <TContainer, TDictionary, TKey, TValue>()
            where TDictionary : IDictionary <TKey, TValue>
        {
            AOT.DictionaryPropertyGenerator <TContainer, TDictionary, TKey, TValue> .Preserve();

            if (PropertyBagStore.TypedStore <IPropertyBag <TDictionary> > .PropertyBag == null)
            {
                PropertyBagStore.AddPropertyBag(new DictionaryPropertyBag <TDictionary, TKey, TValue>());
                PropertyBagStore.AddPropertyBag(new KeyValuePairPropertyBag <TKey, TValue>());
            }
        }
 protected override void VisitPath <TContainer, TValue>(Property <TContainer, TValue> property, ref TContainer container, ref TValue value)
 {
     if (PropertyBagStore.GetPropertyBag <TValue>() is ICollectionPropertyBagAccept <TValue> collectionPropertyBagAccept)
     {
         m_CollectionSearchDataVisitor.SearchData = SearchData;
         collectionPropertyBagAccept.Accept(m_CollectionSearchDataVisitor, ref value);
     }
     else
     {
         SearchData.Add(value?.ToString());
     }
 }
Example #19
0
        public void ClassWithSomeResolvedGenerics_HasPropertyBagGenerated()
        {
            Assert.That(PropertyBagStore.GetPropertyBag(typeof(ClassWithGenericParameterAndGenericBase <int>)), Is.InstanceOf(typeof(ContainerPropertyBag <ClassWithGenericParameterAndGenericBase <int> >)));

            var container = new ClassWithGenericParameterAndGenericBase <int>
            {
                Value0 = 1,
                Value1 = 4.2f
            };

            PropertyContainer.Visit(ref container, new DebugVisitor());
        }
Example #20
0
        IComponentProperty GetOrCreatePropertyForType(int typeIndex, bool isReadOnly)
        {
            var cache = isReadOnly ? m_ReadOnlyPropertyCache : m_ReadWritePropertyCache;

            if (cache.TryGetValue(typeIndex, out var property))
            {
                return(property);
            }

            m_ComponentPropertyConstructor.TypeIndex  = typeIndex;
            m_ComponentPropertyConstructor.IsReadOnly = isReadOnly;
            PropertyBagStore.GetPropertyBag(TypeManager.GetType(typeIndex)).Accept(m_ComponentPropertyConstructor);
            cache.Add(typeIndex, m_ComponentPropertyConstructor.Property);
            return(m_ComponentPropertyConstructor.Property);
        }
Example #21
0
        public void ClassWithGenericBaseClass_HasPropertyBagGenerated()
        {
            Assert.That(PropertyBagStore.GetPropertyBag(typeof(Baz)), Is.InstanceOf(typeof(ContainerPropertyBag <Baz>)));

            var container = new Baz
            {
                Root           = 1,
                Value          = "Hello",
                Value0         = 1.23f,
                Value1         = 42,
                Value0Property = 1.4f
            };

            PropertyContainer.Visit(ref container, new DebugVisitor());
        }
        /// <summary>
        /// Creates a new object that is a copy of the given instance.
        /// </summary>
        /// <param name="obj">The object to clone.</param>
        /// <returns>A new object that is a copy of the given instance.</returns>
        public object Clone(object obj)
        {
            switch (obj)
            {
            case null:
                return(null);

            case ICloneable cloneable:
                return(cloneable.Clone());
            }

            var type = obj.GetType();

#if !UNITY_DOTSRUNTIME
            // UnityEngine references are always by reference.
            if (typeof(UnityEngine.Object).IsAssignableFrom(type))
            {
                return(obj);
            }
#endif
            var instance = type.IsArray
                ? Array.CreateInstance(type.GetElementType(), obj is IList srcList ? srcList.Count : 0)
                : Activator.CreateInstance(type);

            // Visit the source container and write to the dst.
            var properties = PropertyBagStore.GetPropertyBag(type);

            if (null == properties)
            {
                throw new MissingPropertyBagException(type);
            }

            m_References?.Clear();

            m_RootSource      = obj;
            m_RootDestination = instance;

            // Push the instance on the stack.
            m_Stack = instance;
            properties.Accept(this, ref obj);
            return(m_Stack);
        }
Example #23
0
        static PropertyBagDebugInfoStore()
        {
            s_AllDebugInfos    = new List <PropertyBagDebugInfo>();
            s_DebugInfoPerType = new Dictionary <Type, PropertyBagDebugInfo>();
            s_Indices          = new Dictionary <Type, int>();

            foreach (var type in PropertyBagStore.AllTypes)
            {
                var info = new PropertyBagDebugInfo(type, PropertyBagStore.GetPropertyBag(type));
                s_AllDebugInfos.Add(info);
                s_DebugInfoPerType[type] = info;
            }

            s_AllDebugInfos.Sort((lhs, rhs) => string.Compare(lhs.Name, rhs.Name, StringComparison.Ordinal));
            for (var i = 0; i < s_AllDebugInfos.Count; ++i)
            {
                var info = AllDebugInfos[i];
                s_Indices[info.Type] = i;
            }
            PropertyBagStore.NewTypeRegistered += OnPropertyBagRegistered;
        }
        /// <summary>
        /// Gathers all blob asset references within the specified object.
        /// </summary>
        /// <param name="obj">The object to extract all blob asset references from.</param>
        /// <param name="blobAssets">The array where new blob asset references are added.</param>
        /// <param name="blobAssetMap">Mapping to track existing blob asset references encountered.</param>
        /// <exception cref="ArgumentNullException">The given object was null.</exception>
        /// <exception cref="MissingPropertyBagException">The given object has no property bag associated with it.</exception>
        public void GatherBlobAssetReferences(object obj, NativeList <SerializeUtility.BlobAssetPtr> blobAssets, NativeHashMap <SerializeUtility.BlobAssetPtr, int> blobAssetMap)
        {
            if (null == obj)
            {
                throw new ArgumentNullException(nameof(obj));
            }

            var type       = obj.GetType();
            var properties = PropertyBagStore.GetPropertyBag(type);

            if (null == properties)
            {
                throw new MissingPropertyBagException(type);
            }

            m_References?.Clear();

            m_BlobAssets   = blobAssets;
            m_BlobAssetMap = blobAssetMap;

            properties.Accept(this, ref obj);
        }
Example #25
0
        IPropertyBag GetPropertyBag(object obj)
        {
            if (null == obj)
            {
                throw new ArgumentNullException(nameof(obj));
            }

            var type     = obj.GetType();
            var typeInfo = TypeManager.GetTypeInfo(TypeManager.GetTypeIndex(type));

            if (typeInfo.Category == TypeManager.TypeCategory.UnityEngineObject)
            {
                throw new ArgumentException("Cannot remap hybrid components", nameof(obj));
            }

            var properties = PropertyBagStore.GetPropertyBag(type);

            if (null == properties)
            {
                throw new MissingPropertyBagException(type);
            }

            return(properties);
        }
        static void ProcessRequestQueue()
        {
            // Wait until a provider is registered.
            if (!PropertyBagStore.HasProvider)
            {
                return;
            }

            while (s_RequestQueue.TryDequeue(out var info))
            {
                if (PropertyBagStore.Exists(info.Type))
                {
                    continue;
                }

                ProcessRequest(info.Type, info.Options);
                break;
            }

            if (s_RequestQueue.IsEmpty)
            {
                EditorApplication.update -= s_ProcessQueueFunction;
            }
        }
 static DynamicBufferContainer()
 {
     PropertyBagStore.AddPropertyBag(new ListPropertyBag <DynamicBufferContainer <TElement>, TElement>());
 }
 public void ClassWithMultipleNamespaceScopes_HasPropertyBagGenerated()
 {
     Assert.That(PropertyBagStore.GetPropertyBag <NestedNamespace.ClassWithMultipleNamespaceScopes>(), Is.InstanceOf <ContainerPropertyBag <NestedNamespace.ClassWithMultipleNamespaceScopes> >());
 }
 public void ClassWithNestedNamespacesAndTypes_HasPropertyBagGenerated()
 {
     Assert.That(PropertyBagStore.GetPropertyBag <Test.Foo.Bar.ClassWithNestedNamespacesAndTypes>(), Is.InstanceOf <ContainerPropertyBag <Test.Foo.Bar.ClassWithNestedNamespacesAndTypes> >());
 }
Example #30
0
 static void Initialize()
 {
     PropertyBagStore.AddPropertyBag(new AnimationCurvePropertyBag());
     PropertyBagStore.AddPropertyBag(new KeyFramePropertyBag());
 }