I am looking for a way to chain several delegates so the result from one becomes the input of the next. I am trying to use this in equation solving program where portions ar
using GetInvocationlist you can achieve this.
Delegate[] chain = chained.GetInvocationList();
int res = 10;
for( int i = 0; i < chain.Length; i++ )
{
//Call chain[i]
res = chain[i](res);
}
This might help:
public static Func<T1, TResult> Compose<T1, T2, TResult>(Func<T1, T2> innerFunc, Func<T2, TResult> outerFunc) {
return arg => outerFunc(innerFunc(arg));
}
This performs function composition, running innerFunc
and passing the result to outerFunc
when the initial argument is supplied:
Func<double, double> floor = Math.Floor;
Func<double, int> convertToInt = Convert.ToInt32;
Func<double, int> floorAndConvertToInt = Compose(floor, convertToInt);
int result = floorAndConvertToInt(5.62);
Func<double, int> floorThenConvertThenAddTen = Compose(floorAndConvertToInt, i => i + 10);
int result2 = floorThenConvertThenAddTen(64.142);
Yes this is possible - you need to ensure that the return type of the delegate is one that is the parameter type of the delegate being invoked.
A lot of LINQ is built this ways, though you may want to take a look at expressions.
I have been working on a similar problem myself which involved invoking a sequence of delegates and passing the output of one delegate to the next (and so on...) so thought you might be interested to see the code I developed as a proof-of-concept:
static class Program
{
private static IList<Func<int, int>> delegateList =
new List<Func<int, int>>()
{
AddOne, AddOne, AddOne, AddOne, AddOne,
AddOne, AddOne, AddOne, AddOne, AddOne,
};
static void Main(string[] args)
{
int number = 12;
Console.WriteLine("Starting number: {0}", number);
Console.WriteLine("Ending number: {0}",
delegateList.InvokeChainDelegates(number));
Console.ReadLine();
}
public static int AddOne(int num) { return num + 1; }
public static T InvokeChainDelegates<T>(this IEnumerable<Func<T, T>> source,
T startValue)
{
T result = startValue;
foreach (Func<T, T> function in source)
{
result = function(result);
}
return result;
}
}
The sequence has to contain delegates of the same type so is not as powerful as the already accepted answer but with a few tweaks, both bits of code could be combined to provide a powerful solution.
The type of API you are describing is called a Fluent API. Take a look at the preceeding article for a good tutorial.
With regard to delegate chaining, take a look at the LINQ extension methods in .NET 3.5, in particular how lambda functions (delegates) passed to a function result in an IEnumerable result which can then be chained with another extension method + lambda.
In your specific case you might need to create a class called a Functor to accept a delegate and return another Functor which too can be operated on by delegates.
Best regards,