using System; using System.Collections.Generic; using System.Linq; using System.Threading; using Chernobyl.Collections.Generic; namespace Chernobyl.Extensions { /// /// Extension methods for and related types. /// public static class ActionExtensions { /// /// Returns a method that invokes with the /// argument specified by . /// /// The type of the argument expected by /// . /// The method to invoke on invocation of the returned /// method. /// The argument to pass to /// on invocation of the returned method. /// The method whose invocation invokes /// with as its parameter. public static Action Bind(this Action method, T1 arg1) { return () => method(arg1); } /// /// Returns a sequence of methods whose argument is bound to the values /// in . /// /// The argument type expected by . /// The method to be invoked on invocation of the /// returned methods. /// The instances to be provided to /// . /// The methods whose invocation will invoke /// with the as its parameters. public static IEnumerable Bind(this Action method, IEnumerable arguments) { return arguments.Select(method.Bind); } /// /// Returns a method that invokes with the /// argument specified by . /// /// The type of the first argument expected by /// . /// The type of the second argument expected by /// . /// The method to invoke on invocation of the returned /// method. /// The argument to pass to /// on invocation of the returned method. /// /// The method whose invocation invokes /// with as its parameter. /// public static Action Bind(this Action method, T1 arg1) { return arg2 => method(arg1, arg2); } /// /// Returns a sequence of methods whose first argument is bound to the /// values in . /// /// The first argument type expected by . /// The second argument type expected by . /// The method to be invoked on invocation of the /// returned methods. /// The instances to be provided to /// . /// /// The methods whose invocation will invoke /// with the as its parameters. /// public static IEnumerable> Bind(this Action method, IEnumerable firstArguments) { return firstArguments.Select>(method.Bind); } /// /// Returns a method that invokes with the /// argument specified by . /// /// The type of the first argument expected by /// . /// The type of the second argument expected by /// . /// The type of the third argument expected by /// . /// The method to invoke on invocation of the returned /// method. /// The argument to pass to /// on invocation of the returned method. /// /// The method whose invocation invokes /// with as its parameter. /// public static Action Bind(this Action method, T1 arg1) { return (arg2, arg3) => method(arg1, arg2, arg3); } /// /// Returns a method that, when invoked, will invoked the provided /// once for each of the /// provided. The will form the first /// parameter of the . /// /// The first argument type expected by . /// The second argument type expected by . /// The third argument type expected by . /// The method to be invoked on invocation of the /// returned method. /// The instances to be provided to /// . /// /// The method whose invocation will invoke /// with the as its parameters. /// public static IEnumerable> Bind(this Action method, IEnumerable firstArguments) { return firstArguments.Select>(method.Bind); } /// /// Creates a composite method that, when invoked, invokes other methods. /// /// The methods to combine into a single composite /// method. /// The composite method. public static Action Combine(this IEnumerable actions) { return () => actions.For(action => action()); } /// /// Converts a single method taking many arguments to many methods each /// taking one argument, such that, when the returned method are all /// invoked, will be invoked with all of the /// items passed to the returned methods. /// /// The type taken by the methods. /// The callback to be invoked once all of the /// return methods have been invoked.. /// The number of items to collect before /// is invoked. /// The methods to invoke to invoke . public static IEnumerable> AsMany(this Action> callback, int count) { var values = new T[count]; var valuesResolved = 0; return values.Select>((o, index) => value => { values[index] = value; // Invoke the callback once all values have been resolved. if (Interlocked.Increment(ref valuesResolved) == count) { callback(values); valuesResolved = 0; } }); } /// /// Converts many methods taking a single argument to one method taking /// many arguments, such that, when the returned method is invoked, all /// of the provided are invoked. /// /// The type taken by the methods. /// The methods to invoke when the returned method /// is invoked. /// The method to invoke when invoking . public static Action> AsOne(this IEnumerable> methods) { return items => methods.Zip(items).For(pair => pair.First(pair.Second)); } /// /// Converts a method taking one argument into a method that can take /// many of the same argument type. /// /// The type taken by the . /// The method to convert. /// The method to whose invocation invokes /// once for each item. public static Action> AsManyArgumented(this Action method) { return items => items.For(method); } /// /// Invokes the specified methods, passing in the provided method. /// public static void Invoke(this IEnumerable actions) { actions.For(action => action()); } /// /// Invokes the specified methods, passing in the provided method. /// /// The type expected by the method. /// The methods to invoke. /// The parameter to pass to the methods. public static void Invoke(this IEnumerable> actions, T param1) { actions.For(action => action(param1)); } /// /// Returns a method that casts the parameter before passing it to the /// method provided. /// /// The type to cast the parameter to and pass to /// the method provided. /// The method to invoke after the cast. /// The method that, when invoked, invokes /// with its parameter casted. public static Action Cast(this Action action) { return instance => action((TTo)instance); } } }