mirror of
https://github.com/zoriya/Kyoo.git
synced 2025-07-09 03:04:20 -04:00
Remove dead code
This commit is contained in:
parent
d36a20ce5e
commit
e846a1cc18
@ -1,70 +0,0 @@
|
|||||||
// Kyoo - A portable and vast media library solution.
|
|
||||||
// Copyright (c) Kyoo.
|
|
||||||
//
|
|
||||||
// See AUTHORS.md and LICENSE file in the project root for full license information.
|
|
||||||
//
|
|
||||||
// Kyoo is free software: you can redistribute it and/or modify
|
|
||||||
// it under the terms of the GNU General Public License as published by
|
|
||||||
// the Free Software Foundation, either version 3 of the License, or
|
|
||||||
// any later version.
|
|
||||||
//
|
|
||||||
// Kyoo is distributed in the hope that it will be useful,
|
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
// GNU General Public License for more details.
|
|
||||||
//
|
|
||||||
// You should have received a copy of the GNU General Public License
|
|
||||||
// along with Kyoo. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
namespace Kyoo.Utils;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// A set of extensions class for enumerable.
|
|
||||||
/// </summary>
|
|
||||||
public static class EnumerableExtensions
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// If the enumerable is empty, execute an action.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="self">The enumerable to check</param>
|
|
||||||
/// <param name="action">The action to execute is the list is empty</param>
|
|
||||||
/// <typeparam name="T">The type of items inside the list</typeparam>
|
|
||||||
/// <returns>The iterator proxied, there is no dual iterations.</returns>
|
|
||||||
public static IEnumerable<T> IfEmpty<T>(this IEnumerable<T> self, Action action)
|
|
||||||
{
|
|
||||||
static IEnumerable<T> Generator(IEnumerable<T> self, Action action)
|
|
||||||
{
|
|
||||||
using IEnumerator<T> enumerator = self.GetEnumerator();
|
|
||||||
|
|
||||||
if (!enumerator.MoveNext())
|
|
||||||
{
|
|
||||||
action();
|
|
||||||
yield break;
|
|
||||||
}
|
|
||||||
|
|
||||||
do
|
|
||||||
{
|
|
||||||
yield return enumerator.Current;
|
|
||||||
} while (enumerator.MoveNext());
|
|
||||||
}
|
|
||||||
|
|
||||||
return Generator(self, action);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// A foreach used as a function with a little specificity: the list can be null.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="self">The list to enumerate. If this is null, the function result in a no-op</param>
|
|
||||||
/// <param name="action">The action to execute for each arguments</param>
|
|
||||||
/// <typeparam name="T">The type of items in the list</typeparam>
|
|
||||||
public static void ForEach<T>(this IEnumerable<T>? self, Action<T> action)
|
|
||||||
{
|
|
||||||
if (self == null)
|
|
||||||
return;
|
|
||||||
foreach (T i in self)
|
|
||||||
action(i);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,133 +0,0 @@
|
|||||||
// Kyoo - A portable and vast media library solution.
|
|
||||||
// Copyright (c) Kyoo.
|
|
||||||
//
|
|
||||||
// See AUTHORS.md and LICENSE file in the project root for full license information.
|
|
||||||
//
|
|
||||||
// Kyoo is free software: you can redistribute it and/or modify
|
|
||||||
// it under the terms of the GNU General Public License as published by
|
|
||||||
// the Free Software Foundation, either version 3 of the License, or
|
|
||||||
// any later version.
|
|
||||||
//
|
|
||||||
// Kyoo is distributed in the hope that it will be useful,
|
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
// GNU General Public License for more details.
|
|
||||||
//
|
|
||||||
// You should have received a copy of the GNU General Public License
|
|
||||||
// along with Kyoo. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Reflection;
|
|
||||||
using Kyoo.Abstractions.Models.Attributes;
|
|
||||||
|
|
||||||
namespace Kyoo.Utils;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// A class containing helper methods to merge objects.
|
|
||||||
/// </summary>
|
|
||||||
public static class Merger
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Merge two dictionary, if the same key is found on both dictionary, the values of the second one is kept.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="first">The first dictionary to merge</param>
|
|
||||||
/// <param name="second">The second dictionary to merge</param>
|
|
||||||
/// <param name="hasChanged">
|
|
||||||
/// <c>true</c> if a new items has been added to the dictionary, <c>false</c> otherwise.
|
|
||||||
/// </param>
|
|
||||||
/// <typeparam name="T">The type of the keys in dictionaries</typeparam>
|
|
||||||
/// <typeparam name="T2">The type of values in the dictionaries</typeparam>
|
|
||||||
/// <returns>
|
|
||||||
/// A dictionary with the missing elements of <paramref name="second"/>
|
|
||||||
/// set to those of <paramref name="first"/>.
|
|
||||||
/// </returns>
|
|
||||||
public static IDictionary<T, T2>? CompleteDictionaries<T, T2>(
|
|
||||||
IDictionary<T, T2>? first,
|
|
||||||
IDictionary<T, T2>? second,
|
|
||||||
out bool hasChanged
|
|
||||||
)
|
|
||||||
{
|
|
||||||
if (first == null)
|
|
||||||
{
|
|
||||||
hasChanged = true;
|
|
||||||
return second;
|
|
||||||
}
|
|
||||||
|
|
||||||
hasChanged = false;
|
|
||||||
if (second == null)
|
|
||||||
return first;
|
|
||||||
hasChanged = second.Any(x =>
|
|
||||||
!first.ContainsKey(x.Key) || x.Value?.Equals(first[x.Key]) == false
|
|
||||||
);
|
|
||||||
foreach ((T key, T2 value) in first)
|
|
||||||
second.TryAdd(key, value);
|
|
||||||
return second;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Set every non-default values of seconds to the corresponding property of second.
|
|
||||||
/// Dictionaries are handled like anonymous objects with a property per key/pair value
|
|
||||||
/// At the end, the OnMerge method of first will be called if first is a <see cref="IOnMerge"/>
|
|
||||||
/// </summary>
|
|
||||||
/// <example>
|
|
||||||
/// {id: 0, slug: "test"}, {id: 4, slug: "foo"} -> {id: 4, slug: "foo"}
|
|
||||||
/// </example>
|
|
||||||
/// <param name="first">
|
|
||||||
/// The object to complete
|
|
||||||
/// </param>
|
|
||||||
/// <param name="second">
|
|
||||||
/// Missing fields of first will be completed by fields of this item. If second is null, the function no-op.
|
|
||||||
/// </param>
|
|
||||||
/// <param name="where">
|
|
||||||
/// Filter fields that will be merged
|
|
||||||
/// </param>
|
|
||||||
/// <typeparam name="T">Fields of T will be completed</typeparam>
|
|
||||||
/// <returns><paramref name="first"/></returns>
|
|
||||||
public static T Complete<T>(T first, T? second, Func<PropertyInfo, bool>? where = null)
|
|
||||||
{
|
|
||||||
if (second == null)
|
|
||||||
return first;
|
|
||||||
|
|
||||||
Type type = typeof(T);
|
|
||||||
IEnumerable<PropertyInfo> properties = type.GetProperties()
|
|
||||||
.Where(x =>
|
|
||||||
x is { CanRead: true, CanWrite: true }
|
|
||||||
&& Attribute.GetCustomAttribute(x, typeof(NotMergeableAttribute)) == null
|
|
||||||
);
|
|
||||||
|
|
||||||
if (where != null)
|
|
||||||
properties = properties.Where(where);
|
|
||||||
|
|
||||||
foreach (PropertyInfo property in properties)
|
|
||||||
{
|
|
||||||
object? value = property.GetValue(second);
|
|
||||||
|
|
||||||
if (value?.Equals(property.GetValue(first)) == true)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (Utility.IsOfGenericType(property.PropertyType, typeof(IDictionary<,>)))
|
|
||||||
{
|
|
||||||
Type[] dictionaryTypes = Utility
|
|
||||||
.GetGenericDefinition(property.PropertyType, typeof(IDictionary<,>))!
|
|
||||||
.GenericTypeArguments;
|
|
||||||
object?[] parameters = { property.GetValue(first), value, false };
|
|
||||||
object newDictionary = Utility.RunGenericMethod<object>(
|
|
||||||
typeof(Merger),
|
|
||||||
nameof(CompleteDictionaries),
|
|
||||||
dictionaryTypes,
|
|
||||||
parameters
|
|
||||||
)!;
|
|
||||||
if ((bool)parameters[2]!)
|
|
||||||
property.SetValue(first, newDictionary);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
property.SetValue(first, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (first is IOnMerge merge)
|
|
||||||
merge.OnMerge(second);
|
|
||||||
return first;
|
|
||||||
}
|
|
||||||
}
|
|
@ -177,25 +177,6 @@ public static class Utility
|
|||||||
yield return type;
|
yield return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Check if <paramref name="type"/> inherit from a generic type <paramref name="genericType"/>.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="type">The type to check</param>
|
|
||||||
/// <param name="genericType">The generic type to check against (Only generic types are supported like typeof(IEnumerable<>).</param>
|
|
||||||
/// <returns>True if obj inherit from genericType. False otherwise</returns>
|
|
||||||
public static bool IsOfGenericType(Type type, Type genericType)
|
|
||||||
{
|
|
||||||
if (!genericType.IsGenericType)
|
|
||||||
throw new ArgumentException($"{nameof(genericType)} is not a generic type.");
|
|
||||||
|
|
||||||
IEnumerable<Type> types = genericType.IsInterface
|
|
||||||
? type.GetInterfaces()
|
|
||||||
: type.GetInheritanceTree();
|
|
||||||
return types
|
|
||||||
.Prepend(type)
|
|
||||||
.Any(x => x.IsGenericType && x.GetGenericTypeDefinition() == genericType);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Get the generic definition of <paramref name="genericType"/>.
|
/// Get the generic definition of <paramref name="genericType"/>.
|
||||||
/// For example, calling this function with List<string> and typeof(IEnumerable<>) will return IEnumerable<string>
|
/// For example, calling this function with List<string> and typeof(IEnumerable<>) will return IEnumerable<string>
|
||||||
@ -217,147 +198,6 @@ public static class Utility
|
|||||||
.FirstOrDefault(x => x.IsGenericType && x.GetGenericTypeDefinition() == genericType);
|
.FirstOrDefault(x => x.IsGenericType && x.GetGenericTypeDefinition() == genericType);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Retrieve a method from an <see cref="Type"/> with the given name and respect the
|
|
||||||
/// amount of parameters and generic parameters. This works for polymorphic methods.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="type">
|
|
||||||
/// The type owning the method. For non static methods, this is the <c>this</c>.
|
|
||||||
/// </param>
|
|
||||||
/// <param name="flag">
|
|
||||||
/// The binding flags of the method. This allow you to specify public/private and so on.
|
|
||||||
/// </param>
|
|
||||||
/// <param name="name">
|
|
||||||
/// The name of the method.
|
|
||||||
/// </param>
|
|
||||||
/// <param name="generics">
|
|
||||||
/// The list of generic parameters.
|
|
||||||
/// </param>
|
|
||||||
/// <param name="args">
|
|
||||||
/// The list of parameters.
|
|
||||||
/// </param>
|
|
||||||
/// <exception cref="ArgumentException">No method match the given constraints.</exception>
|
|
||||||
/// <returns>The method handle of the matching method.</returns>
|
|
||||||
public static MethodInfo GetMethod(
|
|
||||||
Type type,
|
|
||||||
BindingFlags flag,
|
|
||||||
string name,
|
|
||||||
Type[] generics,
|
|
||||||
object?[] args
|
|
||||||
)
|
|
||||||
{
|
|
||||||
MethodInfo[] methods = type.GetMethods(flag | BindingFlags.Public)
|
|
||||||
.Where(x => x.Name == name)
|
|
||||||
.Where(x => x.GetGenericArguments().Length == generics.Length)
|
|
||||||
.Where(x => x.GetParameters().Length == args.Length)
|
|
||||||
.IfEmpty(() =>
|
|
||||||
{
|
|
||||||
throw new ArgumentException(
|
|
||||||
$"A method named {name} with "
|
|
||||||
+ $"{args.Length} arguments and {generics.Length} generic "
|
|
||||||
+ $"types could not be found on {type.Name}."
|
|
||||||
);
|
|
||||||
})
|
|
||||||
// TODO this won't work but I don't know why.
|
|
||||||
// .Where(x =>
|
|
||||||
// {
|
|
||||||
// int i = 0;
|
|
||||||
// return x.GetGenericArguments().All(y => y.IsAssignableFrom(generics[i++]));
|
|
||||||
// })
|
|
||||||
// .IfEmpty(() => throw new NullReferenceException($"No method {name} match the generics specified."))
|
|
||||||
|
|
||||||
// TODO this won't work for Type<T> because T is specified in arguments but not in the parameters type.
|
|
||||||
// .Where(x =>
|
|
||||||
// {
|
|
||||||
// int i = 0;
|
|
||||||
// return x.GetParameters().All(y => y.ParameterType.IsInstanceOfType(args[i++]));
|
|
||||||
// })
|
|
||||||
// .IfEmpty(() => throw new NullReferenceException($"No method {name} match the parameters's types."))
|
|
||||||
.Take(2)
|
|
||||||
.ToArray();
|
|
||||||
|
|
||||||
if (methods.Length == 1)
|
|
||||||
return methods[0];
|
|
||||||
throw new ArgumentException(
|
|
||||||
$"Multiple methods named {name} match the generics and parameters constraints."
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Run a generic static method for a runtime <see cref="Type"/>.
|
|
||||||
/// </summary>
|
|
||||||
/// <example>
|
|
||||||
/// To run Merger.MergeLists{T} for a List where you don't know the type at compile type,
|
|
||||||
/// you could do:
|
|
||||||
/// <code lang="C#">
|
|
||||||
/// Utility.RunGenericMethod<object>(
|
|
||||||
/// typeof(Utility),
|
|
||||||
/// nameof(MergeLists),
|
|
||||||
/// enumerableType,
|
|
||||||
/// oldValue, newValue, equalityComparer)
|
|
||||||
/// </code>
|
|
||||||
/// </example>
|
|
||||||
/// <param name="owner">The type that owns the method. For non static methods, the type of <c>this</c>.</param>
|
|
||||||
/// <param name="methodName">The name of the method. You should use the <c>nameof</c> keyword.</param>
|
|
||||||
/// <param name="type">The generic type to run the method with.</param>
|
|
||||||
/// <param name="args">The list of arguments of the method</param>
|
|
||||||
/// <typeparam name="T">
|
|
||||||
/// The return type of the method. You can put <see cref="object"/> for an unknown one.
|
|
||||||
/// </typeparam>
|
|
||||||
/// <exception cref="ArgumentException">No method match the given constraints.</exception>
|
|
||||||
/// <returns>The return of the method you wanted to run.</returns>
|
|
||||||
/// <seealso cref="RunGenericMethod{T}(System.Type,string,System.Type[],object[])"/>
|
|
||||||
public static T? RunGenericMethod<T>(
|
|
||||||
Type owner,
|
|
||||||
string methodName,
|
|
||||||
Type type,
|
|
||||||
params object[] args
|
|
||||||
)
|
|
||||||
{
|
|
||||||
return RunGenericMethod<T>(owner, methodName, new[] { type }, args);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Run a generic static method for a multiple runtime <see cref="Type"/>.
|
|
||||||
/// If your generic method only needs one type, see
|
|
||||||
/// <see cref="RunGenericMethod{T}(System.Type,string,System.Type,object[])"/>
|
|
||||||
/// </summary>
|
|
||||||
/// <example>
|
|
||||||
/// To run Merger.MergeLists{T} for a List where you don't know the type at compile type,
|
|
||||||
/// you could do:
|
|
||||||
/// <code>
|
|
||||||
/// Utility.RunGenericMethod<object>(
|
|
||||||
/// typeof(Utility),
|
|
||||||
/// nameof(MergeLists),
|
|
||||||
/// enumerableType,
|
|
||||||
/// oldValue, newValue, equalityComparer)
|
|
||||||
/// </code>
|
|
||||||
/// </example>
|
|
||||||
/// <param name="owner">The type that owns the method. For non static methods, the type of <c>this</c>.</param>
|
|
||||||
/// <param name="methodName">The name of the method. You should use the <c>nameof</c> keyword.</param>
|
|
||||||
/// <param name="types">The list of generic types to run the method with.</param>
|
|
||||||
/// <param name="args">The list of arguments of the method</param>
|
|
||||||
/// <typeparam name="T">
|
|
||||||
/// The return type of the method. You can put <see cref="object"/> for an unknown one.
|
|
||||||
/// </typeparam>
|
|
||||||
/// <exception cref="ArgumentException">No method match the given constraints.</exception>
|
|
||||||
/// <returns>The return of the method you wanted to run.</returns>
|
|
||||||
/// <seealso cref="RunGenericMethod{T}(System.Type,string,System.Type,object[])"/>
|
|
||||||
public static T? RunGenericMethod<T>(
|
|
||||||
Type owner,
|
|
||||||
string methodName,
|
|
||||||
Type[] types,
|
|
||||||
params object?[] args
|
|
||||||
)
|
|
||||||
{
|
|
||||||
if (types.Length < 1)
|
|
||||||
throw new ArgumentException(
|
|
||||||
$"The {nameof(types)} array is empty. At least one type is needed."
|
|
||||||
);
|
|
||||||
MethodInfo method = GetMethod(owner, BindingFlags.Static, methodName, types, args);
|
|
||||||
return (T?)method.MakeGenericMethod(types).Invoke(null, args);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Convert a dictionary to a query string.
|
/// Convert a dictionary to a query string.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user