diff --git a/Kyoo.Common/Utility.cs b/Kyoo.Common/Utility.cs
index a25d9b4f..220b2003 100644
--- a/Kyoo.Common/Utility.cs
+++ b/Kyoo.Common/Utility.cs
@@ -15,8 +15,16 @@ using Kyoo.Models.Attributes;
namespace Kyoo
{
+ ///
+ /// A set of utility functions that can be used everywhere.
+ ///
public static class Utility
{
+ ///
+ /// Is the lambda expression a member (like x => x.Body).
+ ///
+ /// The expression that should be checked
+ /// True if the expression is a member, false otherwise
public static bool IsPropertyExpression(LambdaExpression ex)
{
return ex == null ||
@@ -24,6 +32,12 @@ namespace Kyoo
ex.Body.NodeType == ExpressionType.Convert && ((UnaryExpression)ex.Body).Operand is MemberExpression;
}
+ ///
+ /// Get the name of a property. Usfull for selectors as members ex: Load(x => x.Shows)
+ ///
+ /// The expression
+ /// The name of the expression
+ /// If the expression is not a property, ArgumentException is thrown.
public static string GetPropertyName(LambdaExpression ex)
{
if (!IsPropertyExpression(ex))
@@ -34,6 +48,14 @@ namespace Kyoo
return member!.Member.Name;
}
+ ///
+ /// Get the value of a member (property or field)
+ ///
+ /// The member value
+ /// The owner of this member
+ /// The value boxed as an object
+ /// if or is null.
+ /// The member is not a field or a property.
public static object GetValue([NotNull] this MemberInfo member, [NotNull] object obj)
{
if (member == null)
@@ -48,6 +70,11 @@ namespace Kyoo
};
}
+ ///
+ /// Slugify a string (Replace spaces by -, Uniformise accents é -> e)
+ ///
+ /// The string to slugify
+ /// The slugified string
public static string ToSlug(string str)
{
if (str == null)
@@ -73,6 +100,12 @@ namespace Kyoo
}
+ ///
+ /// Set the image of a show using the type.
+ ///
+ /// The owner of the image
+ /// The url of the image
+ /// The type of the image
public static void SetImage(Show show, string imgUrl, ImageType type)
{
switch(type)
@@ -91,6 +124,13 @@ namespace Kyoo
}
}
+ ///
+ /// Merge two lists, can keep duplicates or remove them.
+ ///
+ /// The first enumarble to merge
+ /// The second enumerable to merge, if items from this list are equals to one from the first, they are not keeped
+ /// Equality function to compare items. If this is null, duplicated elements are kept
+ /// The two list merged as an array
public static T[] MergeLists(IEnumerable first,
IEnumerable second,
Func isEqual = null)
@@ -105,13 +145,20 @@ namespace Kyoo
return list.Concat(second.Where(x => !list.Any(y => isEqual(x, y)))).ToArray();
}
+ ///
+ /// Set every fields of first to those of second. Ignore fields marked with the attribute
+ /// At the end, the OnMerge method of first will be called if first is a
+ ///
+ /// The object to assign
+ /// The object containg new values
+ /// Fields of T will be used
+ ///
public static T Assign(T first, T second)
{
Type type = typeof(T);
IEnumerable properties = type.GetProperties()
- .Where(x => x.CanRead
- && x.CanWrite
- && Attribute.GetCustomAttribute(x, typeof(NotMergableAttribute)) == null);
+ .Where(x => x.CanRead && x.CanWrite
+ && Attribute.GetCustomAttribute(x, typeof(NotMergableAttribute)) == null);
foreach (PropertyInfo property in properties)
{
@@ -124,7 +171,17 @@ namespace Kyoo
return first;
}
- public static T Complete(T first, T second, Func where = null)
+ ///
+ /// Set every default values of first to the value of second. ex: {id: 0, slug: "test"}, {id: 4, slug: "foo"} -> {id: 4, slug: "test"}.
+ /// At the end, the OnMerge method of first will be called if first is a
+ ///
+ /// The object to complete
+ /// Missing fields of first will be completed by fields of this item. If second is null, the function no-op.
+ /// Filter fields that will be merged
+ /// Fields of T will be completed
+ ///
+ /// If first is null
+ public static T Complete([NotNull] T first, [CanBeNull] T second, Func where = null)
{
if (first == null)
throw new ArgumentNullException(nameof(first));
@@ -155,6 +212,16 @@ namespace Kyoo
return first;
}
+ ///
+ /// An advanced function.
+ /// This will set missing values of to the corresponding values of .
+ /// Enumerables will be merged (concatened).
+ /// At the end, the OnMerge method of first will be called if first is a .
+ ///
+ /// The object to complete
+ /// Missing fields of first will be completed by fields of this item. If second is null, the function no-op.
+ /// Fields of T will be merged
+ ///
public static T Merge(T first, T second)
{
if (first == null)
@@ -164,9 +231,8 @@ namespace Kyoo
Type type = typeof(T);
IEnumerable properties = type.GetProperties()
- .Where(x => x.CanRead
- && x.CanWrite
- && Attribute.GetCustomAttribute(x, typeof(NotMergableAttribute)) == null);
+ .Where(x => x.CanRead && x.CanWrite
+ && Attribute.GetCustomAttribute(x, typeof(NotMergableAttribute)) == null);
foreach (PropertyInfo property in properties)
{
@@ -194,6 +260,12 @@ namespace Kyoo
return first;
}
+ ///
+ /// Set every fields of to the default value.
+ ///
+ /// The object to nullify
+ /// Fields of T will be nullified
+ ///
public static T Nullify(T obj)
{
Type type = typeof(T);
@@ -211,6 +283,12 @@ namespace Kyoo
return obj;
}
+ ///
+ /// Return every in the inheritance tree of the parameter (interfaces are not returned)
+ ///
+ /// The starting type
+ /// A list of types
+ /// can't be null
public static IEnumerable GetInheritanceTree([NotNull] this Type type)
{
if (type == null)
@@ -219,6 +297,13 @@ namespace Kyoo
yield return type;
}
+ ///
+ /// Check if inherit from a generic type .
+ ///
+ /// Does this object's type is a
+ /// The generic type to check against (Only generic types are supported like typeof(IEnumerable<>).
+ /// True if obj inherit from genericType. False otherwise
+ /// obj and genericType can't be null
public static bool IsOfGenericType([NotNull] object obj, [NotNull] Type genericType)
{
if (obj == null)
@@ -226,6 +311,13 @@ namespace Kyoo
return IsOfGenericType(obj.GetType(), genericType);
}
+ ///
+ /// Check if inherit from a generic type .
+ ///
+ /// The type to check
+ /// The generic type to check against (Only generic types are supported like typeof(IEnumerable<>).
+ /// True if obj inherit from genericType. False otherwise
+ /// obj and genericType can't be null
public static bool IsOfGenericType([NotNull] Type type, [NotNull] Type genericType)
{
if (type == null)
@@ -241,6 +333,15 @@ namespace Kyoo
return types.Any(x => x.IsGenericType && x.GetGenericTypeDefinition() == genericType);
}
+ ///
+ /// Get the generic definition of .
+ /// For example, calling this function with List<string> and typeof(IEnumerable<>) will return IEnumerable<string>
+ ///
+ /// The type to check
+ /// The generic type to check against (Only generic types are supported like typeof(IEnumerable<>).
+ /// The generic definition of genericType that type inherit or null if type does not implement the genric type.
+ /// and can't be null
+ /// must be a generic type
public static Type GetGenericDefinition([NotNull] Type type, [NotNull] Type genericType)
{
if (type == null)
@@ -256,6 +357,15 @@ namespace Kyoo
return types.FirstOrDefault(x => x.IsGenericType && x.GetGenericTypeDefinition() == genericType);
}
+ ///
+ /// A Select where the index of the item can be used.
+ ///
+ /// The IEnumerable to map. If self is null, an empty list is returned
+ /// The function that will map each items
+ /// The type of items in
+ /// The type of items in the returned list
+ /// The list mapped.
+ /// mapper can't be null
public static IEnumerable Map([CanBeNull] this IEnumerable self,
[NotNull] Func mapper)
{
@@ -274,6 +384,16 @@ namespace Kyoo
}
}
+ ///
+ /// A map where the mapping function is asynchronous.
+ /// Note: might interest you.
+ ///
+ /// The IEnumerable to map. If self is null, an empty list is returned
+ /// The asynchronous function that will map each items
+ /// The type of items in
+ /// The type of items in the returned list
+ /// The list mapped as an AsyncEnumerable
+ /// mapper can't be null
public static async IAsyncEnumerable MapAsync([CanBeNull] this IEnumerable self,
[NotNull] Func> mapper)
{
@@ -292,6 +412,15 @@ namespace Kyoo
}
}
+ ///
+ /// An asynchronous version of Select.
+ ///
+ /// The IEnumerable to map
+ /// The asynchronous function that will map each items
+ /// The type of items in
+ /// The type of items in the returned list
+ /// The list mapped as an AsyncEnumerable
+ /// mapper can't be null
public static async IAsyncEnumerable SelectAsync([CanBeNull] this IEnumerable self,
[NotNull] Func> mapper)
{
@@ -306,6 +435,13 @@ namespace Kyoo
yield return await mapper(enumerator.Current);
}
+ ///
+ /// Convert an AsyncEnumerable to a List by waiting for every item.
+ ///
+ /// The async list
+ /// The type of items in the async list and in the returned list.
+ /// A task that will return a simple list
+ /// The list can't be null
public static async Task> ToListAsync([NotNull] this IAsyncEnumerable self)
{
if (self == null)
@@ -318,6 +454,13 @@ namespace Kyoo
return ret;
}
+ ///
+ /// If the enumerable is empty, execute an action.
+ ///
+ /// The enumerable to check
+ /// The action to execute is the list is empty
+ /// The type of items inside the list
+ ///
public static IEnumerable IfEmpty(this IEnumerable self, Action action)
{
using IEnumerator enumerator = self.GetEnumerator();
@@ -335,6 +478,12 @@ namespace Kyoo
while (enumerator.MoveNext());
}
+ ///
+ /// A foreach used as a function with a little specificity: the list can be null.
+ ///
+ /// The list to enumerate. If this is null, the function result in a no-op
+ /// The action to execute for each arguments
+ /// The type of items in the list
public static void ForEach([CanBeNull] this IEnumerable self, Action action)
{
if (self == null)
@@ -343,6 +492,11 @@ namespace Kyoo
action(i);
}
+ ///
+ /// A foreach used as a function with a little specificity: the list can be null.
+ ///
+ /// The list to enumerate. If this is null, the function result in a no-op
+ /// The action to execute for each arguments
public static void ForEach([CanBeNull] this IEnumerable self, Action