From 047ea1a3f0e2e9bf5fc8259d63fc10d0b54676f8 Mon Sep 17 00:00:00 2001 From: Zoe Roux Date: Tue, 13 Apr 2021 13:14:57 +0200 Subject: [PATCH] Adding documentation to Utility --- Kyoo.Common/Utility.cs | 168 +++++++++++++++++++++++++++++++++++++++-- Kyoo/Program.cs | 12 +++ Kyoo/Startup.cs | 3 + 3 files changed, 176 insertions(+), 7 deletions(-) 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 action) { if (self == null) diff --git a/Kyoo/Program.cs b/Kyoo/Program.cs index 474a79b3..81e73def 100644 --- a/Kyoo/Program.cs +++ b/Kyoo/Program.cs @@ -7,8 +7,15 @@ using Microsoft.VisualBasic.FileIO; namespace Kyoo { + /// + /// Program entrypoint. + /// public static class Program { + /// + /// Main function of the program + /// + /// Command line arguments public static async Task Main(string[] args) { if (args.Length > 0) @@ -42,6 +49,11 @@ namespace Kyoo await host.Build().RunAsync(); } + /// + /// Createa a web host + /// + /// Command line parameters that can be handled by kestrel + /// A new web host instance private static IWebHostBuilder CreateWebHostBuilder(string[] args) => WebHost.CreateDefaultBuilder(args) .UseKestrel(config => { config.AddServerHeader = false; }) diff --git a/Kyoo/Startup.cs b/Kyoo/Startup.cs index 165db8cd..ac05a36d 100644 --- a/Kyoo/Startup.cs +++ b/Kyoo/Startup.cs @@ -23,6 +23,9 @@ using Microsoft.Extensions.Logging; namespace Kyoo { + /// + /// The Startup class is used to configure the AspNet's webhost. + /// public class Startup { private readonly IConfiguration _configuration;