mirror of
https://github.com/Artemis-RGB/Artemis
synced 2026-11-11 19:36:28 +00:00
Data model - Support all lists implementing IEnumerable<>
This commit is contained in:
1 parent
17d41647b6
commit
3b6753a0ff
9 files changed
+91
-128
No files matched your search
@@ -88,11 +88,33 @@ namespace Artemis.Core
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the default value of the given type
|
||||
/// Returns the default value of the given type
|
||||
/// </summary>
|
||||
public static object GetDefault(this Type type)
|
||||
{
|
||||
return type.IsValueType ? Activator.CreateInstance(type) : null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether the given type is a generic enumerable
|
||||
/// </summary>
|
||||
public static bool IsGenericEnumerable(this Type type)
|
||||
{
|
||||
return type.GetInterfaces().Any(x =>
|
||||
x.IsGenericType &&
|
||||
x.GetGenericTypeDefinition() == typeof(IEnumerable<>));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines the type of the provided generic enumerable type
|
||||
/// </summary>
|
||||
public static Type? GetGenericEnumerableType(this Type type)
|
||||
{
|
||||
Type enumerableType = type.GetInterfaces().FirstOrDefault(x =>
|
||||
x.IsGenericType &&
|
||||
x.GetGenericTypeDefinition() == typeof(IEnumerable<>));
|
||||
|
||||
return enumerableType?.GenericTypeArguments[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -93,7 +93,7 @@ namespace Artemis.Core
|
||||
if (ListPath != null)
|
||||
{
|
||||
Type listType = ListPath.GetPropertyType()!;
|
||||
ListType = listType.GetGenericArguments()[0];
|
||||
ListType = listType.GetGenericEnumerableType();
|
||||
IsPrimitiveList = ListType.IsPrimitive || ListType.IsEnum || ListType == typeof(string);
|
||||
|
||||
// Create a new root group
|
||||
@@ -129,10 +129,10 @@ namespace Artemis.Core
|
||||
|
||||
if (!Children.Any())
|
||||
return false;
|
||||
if (!(target is IList list))
|
||||
if (!(target is IEnumerable enumerable))
|
||||
return false;
|
||||
|
||||
IEnumerable<object> objectList = list.Cast<object>();
|
||||
IEnumerable<object> objectList = enumerable.Cast<object>();
|
||||
return ListOperator switch
|
||||
{
|
||||
ListOperator.Any => objectList.Any(o => Children[0].EvaluateObject(o)),
|
||||
@@ -180,14 +180,14 @@ namespace Artemis.Core
|
||||
DataModelPath listPath = new DataModelPath(null, Entity.ListPath);
|
||||
Type listType = listPath.GetPropertyType()!;
|
||||
// Can't check this on an invalid list, if it becomes valid later lets hope for the best
|
||||
if (listPath.IsValid && !typeof(IList).IsAssignableFrom(listType))
|
||||
if (listPath.IsValid && !listPath.PointsToList)
|
||||
return;
|
||||
|
||||
ListPath = listPath;
|
||||
SubscribeToListPath();
|
||||
if (ListPath.IsValid)
|
||||
{
|
||||
ListType = listType.GetGenericArguments()[0];
|
||||
ListType = listType.GetGenericEnumerableType();
|
||||
IsPrimitiveList = ListType.IsPrimitive || ListType.IsEnum || ListType == typeof(string);
|
||||
}
|
||||
else
|
||||
|
||||
@@ -114,8 +114,14 @@ namespace Artemis.Core
|
||||
/// <summary>
|
||||
/// Gets a boolean indicating whether this data model path points to a list
|
||||
/// </summary>
|
||||
public bool PointsToList => Segments.LastOrDefault()?.GetPropertyType() != null &&
|
||||
typeof(IList).IsAssignableFrom(Segments.LastOrDefault()?.GetPropertyType());
|
||||
public bool PointsToList
|
||||
{
|
||||
get
|
||||
{
|
||||
Type? type = GetPropertyType();
|
||||
return type?.IsGenericEnumerable() ?? false;
|
||||
}
|
||||
}
|
||||
|
||||
internal DataModelPathEntity Entity { get; }
|
||||
|
||||
|
||||
@@ -142,79 +142,6 @@ namespace Artemis.Core.DataModelExpansions
|
||||
return value as T;
|
||||
}
|
||||
|
||||
internal bool ContainsPath(string? path)
|
||||
{
|
||||
if (path == null)
|
||||
return false;
|
||||
string[] parts = path.Split('.');
|
||||
Type? current = GetType();
|
||||
foreach (string part in parts)
|
||||
{
|
||||
PropertyInfo? property = current?.GetProperty(part);
|
||||
current = property?.PropertyType;
|
||||
if (property == null)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
internal Type GetTypeAtPath(string path)
|
||||
{
|
||||
if (!ContainsPath(path))
|
||||
return null;
|
||||
|
||||
string[] parts = path.Split('.');
|
||||
Type current = GetType();
|
||||
|
||||
Type result = null;
|
||||
foreach (string part in parts)
|
||||
{
|
||||
PropertyInfo? property = current.GetProperty(part);
|
||||
current = property.PropertyType;
|
||||
result = property.PropertyType;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
internal Type GetListTypeInPath(string path)
|
||||
{
|
||||
if (!ContainsPath(path))
|
||||
return null;
|
||||
|
||||
string[] parts = path.Split('.');
|
||||
Type current = GetType();
|
||||
|
||||
int index = 0;
|
||||
foreach (string part in parts)
|
||||
{
|
||||
// Only return a type if the path CONTAINS a list, not if it points TO a list
|
||||
if (index == parts.Length - 1)
|
||||
return null;
|
||||
|
||||
PropertyInfo? property = current.GetProperty(part);
|
||||
|
||||
// For lists, look into the list type instead of the list itself
|
||||
if (typeof(IList).IsAssignableFrom(property.PropertyType))
|
||||
return property.PropertyType.GetGenericArguments()[0];
|
||||
|
||||
current = property.PropertyType;
|
||||
index++;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
internal Type GetListTypeAtPath(string path)
|
||||
{
|
||||
if (!ContainsPath(path))
|
||||
return null;
|
||||
|
||||
Type child = GetTypeAtPath(path);
|
||||
return child.GenericTypeArguments.Length > 0 ? child.GenericTypeArguments[0] : null;
|
||||
}
|
||||
|
||||
#region Events
|
||||
|
||||
/// <summary>
|
||||
|
||||
Reference in new issue
Block a user