Files
sbox-public/engine/Sandbox.System/SerializedObject/SerializedCollection.cs
s&box team 71f266059a Open source release
This commit imports the C# engine code and game files, excluding C++ source code.

[Source-Commit: ceb3d758046e50faa6258bc3b658a30c97743268]
2025-11-24 09:05:18 +00:00

144 lines
3.1 KiB
C#

namespace Sandbox;
public abstract class SerializedCollection : SerializedObject
{
public Type KeyType { get; internal set; }
public Type ValueType { get; internal set; }
public Action OnEntryAdded;
public Action OnEntryRemoved;
object _targetObject;
public object TargetObject => _targetObject;
public Func<SerializedProperty, SerializedObject> PropertyToObject;
public virtual void SetTargetObject( object obj, SerializedProperty property )
{
_targetObject = obj;
ParentProperty = property;
}
public virtual bool Remove( SerializedProperty property ) => false;
public virtual bool RemoveAt( object index ) => false;
public virtual bool Add( object value ) => false;
public virtual bool Add( object key, object value ) => false;
public virtual SerializedProperty NewKeyProperty() => null;
internal static SerializedCollection Create( Type type )
{
if ( IsDictionaryType( type, out var keyType, out var valueType ) )
{
return new SerializedDictionary
{
KeyType = keyType,
ValueType = valueType
};
}
if ( type.IsSZArray && type.IsAssignableTo( typeof( Array ) ) )
{
return new SerializedArray
{
KeyType = typeof( int ),
ValueType = type.GetElementType()
};
}
if ( IsListType( type, out var listElemType ) )
{
return new SerializedList
{
KeyType = typeof( int ),
ValueType = listElemType
};
}
if ( IsSetType( type, out var setElemType ) )
{
return new SerializedSet
{
KeyType = setElemType,
ValueType = setElemType
};
}
return null;
}
private static bool IsDictionaryType( Type type, out Type keyType, out Type valueType )
{
keyType = null;
valueType = null;
if ( !type.IsAssignableTo( typeof( System.Collections.IDictionary ) ) )
{
return false;
}
foreach ( var @interface in type.GetInterfaces() )
{
if ( !@interface.IsConstructedGenericType ) continue;
if ( @interface.GetGenericTypeDefinition() != typeof( IDictionary<,> ) ) continue;
keyType = @interface.GetGenericArguments()[0];
valueType = @interface.GetGenericArguments()[1];
return true;
}
return false;
}
private static bool IsListType( Type type, out Type valueType )
{
valueType = null;
if ( !type.IsAssignableTo( typeof( System.Collections.IList ) ) )
{
return false;
}
foreach ( var @interface in type.GetInterfaces() )
{
if ( !@interface.IsConstructedGenericType ) continue;
if ( @interface.GetGenericTypeDefinition() != typeof( IList<> ) ) continue;
valueType = @interface.GetGenericArguments()[0];
return true;
}
return false;
}
private static bool IsSetType( Type type, out Type valueType )
{
valueType = null;
// Early out if this isn't even an enumerable
// Unfortunately, there is no non-generic System.Collections.ISet
if ( !type.IsAssignableTo( typeof( System.Collections.IEnumerable ) ) )
{
return false;
}
foreach ( var @interface in type.GetInterfaces() )
{
if ( !@interface.IsConstructedGenericType ) continue;
if ( @interface.GetGenericTypeDefinition() != typeof( ISet<> ) ) continue;
valueType = @interface.GetGenericArguments()[0];
return true;
}
return false;
}
}