你可以将一个委托的结果链接成C#中另一个委托的输入吗?

时间:2012-01-04 14:37:40

标签: c# delegates chaining

我正在寻找一种链接多个委托的方法,因此一个委托的结果成为下一个委托的输入。我试图在方程求解程序中使用它,其中部分通过不同的方法完成。这个想法是,当你构建方程式时,程序会添加代理并按特定顺序链接它们,因此可以正确解决。如果有更好的方法来解决问题,请分享。

5 个答案:

答案 0 :(得分:7)

这可能会有所帮助:

public static Func<T1, TResult> Compose<T1, T2, TResult>(Func<T1, T2> innerFunc, Func<T2, TResult> outerFunc) {
    return arg => outerFunc(innerFunc(arg));
}

执行function composition,运行innerFunc并在提供初始参数时将结果传递给outerFunc

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);

答案 1 :(得分:3)

是的,这是可能的 - 您需要确保委托的返回类型是被调用的委托的参数类型。

很多LINQ都是以这种方式构建的,不过你可能想看看expressions

答案 2 :(得分:0)

您描述的API类型称为Fluent API。查看前面的文章以获得一个好的教程。

关于委托链接,请看一下.NET 3.5中的LINQ扩展方法,特别是lambda函数(委托)如何传递给IEnumerable结果中的函数结果,然后可以用另一个扩展方法+ lambda链接

在您的特定情况下,您可能需要创建一个名为Functor的类来接受委托并返回另一个也可由委托操作的Functor。

致以最诚挚的问候,

答案 3 :(得分:0)

使用GetInvocationlist可以实现此目的。

 Delegate[] chain = chained.GetInvocationList();

        int res = 10;
        for( int i = 0; i < chain.Length; i++ ) 
          {
              //Call chain[i]
                res =  chain[i](res);
          }

答案 4 :(得分:0)

我自己一直在研究一个类似的问题,包括调用委托的序列并将一个委托的输出传递给下一个委托(依此类推......)以为你可能会感兴趣看到我开发的代码作为概念验证:

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;
    }
}

序列必须包含相同类型的委托,因此不像已经接受的答案那样强大,但是通过一些调整,两个代码位可以组合起来提供强大的解决方案。