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)); }
/// <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>()); }
/// <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>()); } }
/// <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>()); } }
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; }
/// <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>()); } }
static void Initialize() { if (s_Registered) { return; } s_Registered = true; PropertyBagStore.RegisterProvider(new ReflectedPropertyBagProvider()); }
/// <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>()); } }
/// <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>()); } }
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()); }
/// <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()); } }
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()); }
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); }
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); }
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); }
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> >()); }
static void Initialize() { PropertyBagStore.AddPropertyBag(new AnimationCurvePropertyBag()); PropertyBagStore.AddPropertyBag(new KeyFramePropertyBag()); }