public void SetProperties(RobloxDocument document, Instance instance, PropertyCollection propertyCollection)
        {
            var instanceType = instance.GetType();

            foreach (var property in propertyCollection)
            {
                if (ReflectionMappingManager.HasMappedClrProperty(instanceType, property.Name))
                {
                    var mappedPropertyTuple = ReflectionMappingManager.GetMappedClrProperty(instanceType, property.Name);
                    if (mappedPropertyTuple.Item2 != PropertyType.Referent)
                    {
                        mappedPropertyTuple.Item1.SetValue(instance, property.Get());
                    }
                    else
                    {
                        var referent = (int)property.Get();
                        if (referent != 0)
                        // It seems like in many cases 0 means no referent? For example, gui object's next selection property. TODO look into this.
                        {
                            var inst = (referent != -1) ? document.ReferentProvider.GetCached(referent) : null;
                            mappedPropertyTuple.Item1.SetValue(instance, inst);
                        }
                    }
                }
                else
                {
                    instance.UnmanagedProperties.Add(property.Name, property);
                }
            }
        }
        private T GetPropertyValue <T>(string propertyName, Instance instance, Type instanceType, PropertyType propertyType, ReferentProvider referentProvider)
        {
            if (ReflectionMappingManager.HasMappedClrProperty(instanceType, propertyName))
            {
                var propertyTuple = ReflectionMappingManager.PropertyCache[instanceType][propertyName];

                if (propertyType != PropertyType.Referent)
                {
                    var propertyValue = propertyTuple.Item1.GetValue(instance);
                    if (propertyValue != null)
                    {
                        return((T)propertyValue);
                    }
                    else
                    {
                        return((T)ReflectionMappingManager.GetDefaultValue(instanceType, propertyName, propertyType));
                    }
                }
                else
                {
                    var referentObj = propertyTuple.Item1.GetValue(instance);
                    if (referentObj != null)
                    {
                        return
                            ((T)(object)referentProvider.GetReferent((Instance)propertyTuple.Item1.GetValue(instance)));
                    }
                    else
                    {
                        return((T)ReflectionMappingManager.GetDefaultValueForType(PropertyType.Referent));
                    }
                }
            }
            else if (instance.UnmanagedProperties.ContainsKey(propertyName))
            {
                var objValue = instance.UnmanagedProperties[propertyName].Get();
                if (objValue != null)
                {
                    return((T)objValue);
                }
                else
                {
                    return((T)ReflectionMappingManager.GetDefaultValueForType(propertyType));
                }
            }
            else
            {
                return((T)ReflectionMappingManager.GetDefaultValueForType(propertyType));
            }
        }