A lightweight IOC Container that is powerful enough to do all the things you need it to do.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

56 lines
3.7 KiB

// Author: Gockner, Simon
// Created: 2019-07-02
// Copyright(c) 2019 SimonG. All Rights Reserved.
namespace LightweightIocContainer;
internal static class EnumerableExtension
{
/// <summary>
/// Returns the first element of a <see cref="IEnumerable{T}"/>, or a new instance of a given <see cref="Type"/> if the <see cref="IEnumerable{T}"/> contains no elements
/// </summary>
/// <typeparam name="TSource">The source <see cref="Type"/> of the <see cref="IEnumerable{T}"/></typeparam>
/// <typeparam name="TGiven">The given <see cref="Type"/> to return if the <see cref="IEnumerable{T}"/> contains no elements</typeparam>
/// <param name="source">The given <see cref="IEnumerable{T}"/></param>
/// <returns>The first element of the <see cref="IEnumerable{T}"/>, or a new instance of a given <see cref="Type"/> if the <see cref="IEnumerable{T}"/> contains no elements</returns>
public static TSource FirstOrGiven<TSource, TGiven>(this IReadOnlyCollection<TSource> source) where TGiven : TSource, new() =>
source.TryGetFirst<TSource, TGiven>(null);
/// <summary>
/// Returns the first element of a <see cref="IEnumerable{T}"/> that satisfies a condition, or a new instance of a given <see cref="Type"/> if no such element is found
/// </summary>
/// <typeparam name="TSource">The source <see cref="Type"/> of the <see cref="IEnumerable{T}"/></typeparam>
/// <typeparam name="TGiven">The given <see cref="Type"/> to return if the <see cref="IEnumerable{T}"/> contains no element that satisfies the given condition</typeparam>
/// <param name="source">The given <see cref="IEnumerable{T}"/></param>
/// <param name="predicate">A function to test each element for a condition</param>
/// <returns>The first element of the <see cref="IEnumerable{T}"/> that satisfies a condition, or a new instance of the given <see cref="Type"/> if no such element is found</returns>
public static TSource FirstOrGiven<TSource, TGiven>(this IReadOnlyCollection<TSource> source, Func<TSource, bool> predicate) where TGiven : TSource, new() =>
source.TryGetFirst<TSource, TGiven>(predicate);
/// <summary>
/// Tries to get the first element of the given <see cref="IEnumerable{T}"/> or creates a new element of a given <see cref="Type"/> when no element is found
/// </summary>
/// <typeparam name="TSource">The source <see cref="Type"/> of the <see cref="IEnumerable{T}"/></typeparam>
/// <typeparam name="TGiven">The given <see cref="Type"/> to create a new element when no fitting element is found</typeparam>
/// <param name="source">The given <see cref="IEnumerable{T}"/></param>
/// <param name="predicate">A function to test each element for a condition</param>
/// <returns>The first element of the <see cref="IEnumerable{T}"/> or a new instance of the given <see cref="Type"/> when no element is found</returns>
private static TSource TryGetFirst<TSource, TGiven>(this IReadOnlyCollection<TSource> source, Func<TSource, bool>? predicate) where TGiven : TSource, new() =>
predicate is null ?
!source.Any() ? new TGiven()
: source.First()
: source.Any(predicate) ? source.First(predicate)
: new TGiven();
/// <summary>
/// Executes an <see cref="Action{T}"/> for each item in an <see cref="IEnumerable{T}"/>
/// </summary>
/// <param name="enumerable">The <see cref="IEnumerable{T}"/></param>
/// <param name="action">The <see cref="Action{T}"/></param>
/// <typeparam name="T">The <see cref="Type"/> of the items in the <see cref="IEnumerable{T}"/></typeparam>
public static void ForEach<T>(this IEnumerable<T> enumerable, Action<T> action)
{
foreach (T item in enumerable)
action(item);
}
}