diff --git a/MonkeyLoader/IdentifiableExtensions.cs b/MonkeyLoader/IdentifiableExtensions.cs
index cbe400b..5a15f6e 100644
--- a/MonkeyLoader/IdentifiableExtensions.cs
+++ b/MonkeyLoader/IdentifiableExtensions.cs
@@ -1,56 +1,183 @@
using MonkeyLoader.Meta;
using System;
using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MonkeyLoader
{
+ ///
+ /// Contains extension methods dealing with s.
+ ///
public static class IdentifiableExtensions
{
+ ///
+ /// Finds the nearest parent of this
+ /// that satisfies the given .
+ ///
+ /// The type of the parent to look for.
+ /// The to start looking from.
+ /// The predicate that a potential parent must satisfy.
+ /// The parent satisfying the .
+ /// When no suitable parent was found.
+ public static TParentIdentifiable FindNearestParent(this IIdentifiable identifiable, Predicate predicate)
+ where TParentIdentifiable : IIdentifiable
+ {
+ if (!identifiable.TryFindNearestParent(predicate, out var parentIdentifiable))
+ throw new InvalidOperationException("No suitable parent found!");
+
+ return parentIdentifiable;
+ }
+
+ ///
+ /// Finds the nearest parent of this .
+ ///
+ /// The type of the parent to look for.
+ /// The to start looking from.
+ /// The found parent.
+ /// When no suitable parent was found.
+ public static TParentIdentifiable FindNearestParent(this IIdentifiable identifiable)
+ where TParentIdentifiable : IIdentifiable
+ {
+ if (!identifiable.TryFindNearestParent(out TParentIdentifiable? parentIdentifiable))
+ throw new InvalidOperationException("No suitable parent found!");
+
+ return parentIdentifiable;
+ }
+
+ /// The identifiable collection to start from.
+ ///
public static IIdentifiableSearch Get(this IIdentifiableCollection identifiableCollection)
where TIdentifiable : IIdentifiable
=> new IdentifiableSearch(identifiableCollection.Items);
+ /// The nested identifiable collection to start from.
+ ///
public static INestedIdentifiableSearch Get(this INestedIdentifiableCollection nestedIdentifiableCollection)
where TIdentifiable : INestedIdentifiable
=> new NestedIdentifiableSearch(nestedIdentifiableCollection.Items);
+ ///
+ /// Starts a search for a child from this object.
+ ///
+ /// The type of the identifiable owner to start from.
+ /// The type of the nested to find.
+ /// The identifiable owner to start from.
+ /// The search object for it.
public static IIdentifiableOwnerSearch Get(this IIdentifiableOwner identifiableOwner)
where TOwner : IIdentifiableOwner
where TIdentifiable : INestedIdentifiable
=> new NestedIdentifiableSearch(identifiableOwner.Items, identifiableOwner.FullId);
+ ///
public static IIdentifiableOwnerSearch Get(this IIdentifiableOwner identifiableOwner)
where TIdentifiable : INestedIdentifiable
=> new NestedIdentifiableSearch(identifiableOwner.Items, identifiableOwner.FullId);
+ /// The nested identifiable owner to start from.
+ ///
public static INestedIdentifiableOwnerSearch Get(this INestedIdentifiableOwner nestedIdentifiableOwner)
where TIdentifiable : INestedIdentifiable
=> new NestedIdentifiableSearch(nestedIdentifiableOwner.Items, nestedIdentifiableOwner.FullId);
+ /// The nested identifiable collection to start from.
+ ///
public static IEnumerable GetAll(this INestedIdentifiableCollection nestedIdentifiableCollection)
where TIdentifiable : INestedIdentifiable
=> nestedIdentifiableCollection.Items;
+ ///
+ /// Gets an enumerable of all child from this object.
+ ///
+ /// The type of the nested s to enumerate.
+ /// The identifiable collection to start from.
+ /// An enumerable of all child .
+ public static IEnumerable GetAll(this IIdentifiableCollection identifiableCollection)
+ where TIdentifiable : IIdentifiable
+ => identifiableCollection.Items;
+
+ ///
+ /// Tries to find the nearest parent of this
+ /// that satisfies the given .
+ ///
+ /// The type of the parent to look for.
+ /// The to start looking from.
+ /// The predicate that a potential parent must satisfy.
+ /// The parent satisfying the if found; otherwise, default.
+ /// true if a parent satisfying the was found; otherwise, false.
+ public static bool TryFindNearestParent(this IIdentifiable identifiable,
+ Predicate predicate, [NotNullWhen(true)] out TParentIdentifiable? parentIdentifiable)
+ where TParentIdentifiable : IIdentifiable
+ {
+ while (identifiable.TryFindNearestParent(out parentIdentifiable))
+ {
+ if (predicate(parentIdentifiable))
+ return true;
+
+ if (parentIdentifiable is not INestedIdentifiable)
+ break;
+
+ identifiable = (INestedIdentifiable)parentIdentifiable;
+ }
+
+ parentIdentifiable = default;
+ return false;
+ }
+
+ ///
+ /// Tries to find the nearest parent of this .
+ ///
+ /// The type of the parent to look for.
+ /// The to start looking from.
+ /// The parent if found; otherwise, default.
+ /// true if a parent was found; otherwise, false.
+ public static bool TryFindNearestParent(this IIdentifiable identifiable, [NotNullWhen(true)] out TParentIdentifiable? parentIdentifiable)
+ where TParentIdentifiable : IIdentifiable
+ {
+ while (identifiable is not TParentIdentifiable and INestedIdentifiable nestedCurrent)
+ identifiable = nestedCurrent.Parent;
+
+ if (identifiable is TParentIdentifiable parent)
+ {
+ parentIdentifiable = parent;
+ return true;
+ }
+
+ parentIdentifiable = default;
+ return false;
+ }
+
+ /// The nested identifiable owner to start from.
+ ///
public static INestedIdentifiableOwnerTrySearch TryGet(this INestedIdentifiableOwner nestedIdentifiableOwner)
where TIdentifiable : INestedIdentifiable
=> new NestedIdentifiableSearch(nestedIdentifiableOwner.Items, nestedIdentifiableOwner.FullId);
+ ///
+ /// Starts a try-search for a child from this object.
+ ///
+ /// The try-search object for it.
+ ///
public static IIdentifiableOwnerTrySearch TryGet(this IIdentifiableOwner identifiableOwner)
where TOwner : IIdentifiableOwner
where TIdentifiable : INestedIdentifiable
=> new NestedIdentifiableSearch(identifiableOwner.Items, identifiableOwner.FullId);
+ ///
public static IIdentifiableOwnerTrySearch TryGet(this IIdentifiableOwner identifiableOwner)
where TIdentifiable : INestedIdentifiable
=> new NestedIdentifiableSearch(identifiableOwner.Items, identifiableOwner.FullId);
+ /// The identifiable collection to start from.
+ ///
public static IIdentifiableTrySearch TryGet(this IIdentifiableCollection identifiableCollection)
where TIdentifiable : IIdentifiable
=> new IdentifiableSearch(identifiableCollection.Items);
+ /// The nested identifiable collection to start from.
+ ///
public static INestedIdentifiableTrySearch TryGet(this INestedIdentifiableCollection nestedIdentifiableCollection)
where TIdentifiable : INestedIdentifiable
=> new NestedIdentifiableSearch(nestedIdentifiableCollection.Items);