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

前端 未结 5 1069
春和景丽
春和景丽 2021-01-14 13:09

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

相关标签:
5条回答
  • 2021-01-14 13:49

    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);
              }
    
    0 讨论(0)
  • 2021-01-14 14:01

    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);
    
    0 讨论(0)
  • 2021-01-14 14:07

    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.

    0 讨论(0)
  • 2021-01-14 14:08

    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.

    0 讨论(0)
  • 2021-01-14 14:09

    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,

    0 讨论(0)
提交回复
热议问题