Can you chain the result of one delegate to be the input of another in C#?
Asked Answered
A

5

3

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 are done by different methods. The idea is that when you are building the equation the program adds the delegates and chains them in a particular order, so it can be solved properly. If there is a better way to approach the problem please share.

Audacity answered 4/1, 2012 at 14:37 Comment(1)
Perhaps Expression Trees would be worth looking into (msdn.microsoft.com/en-us/library/bb397951.aspx)?Flannery
L
7

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);
Liege answered 4/1, 2012 at 14:43 Comment(0)
B
3

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.

Bloat answered 4/1, 2012 at 14:40 Comment(2)
I figured that all should want the same input type and return that particular type.Audacity
@Audacity - If you want each to be chainable to the others, yes. This is the basis for fluent interfaces.Bloat
M
0

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,

Messick answered 4/1, 2012 at 14:43 Comment(0)
I
0

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);
          }
Intracellular answered 4/1, 2012 at 14:44 Comment(0)
S
0

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.

Scheller answered 28/11, 2012 at 20:24 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.