在事件/功能链中调用函数?

时间:2010-04-10 15:11:08

标签: c#

我有3个功能。可以按任何顺序调用它们(以后它们可能需要特定的顺序)。 一个函数的返回值应该是下一个函数的第一个参数。我该怎么做呢?我在想的是下面的东西。这是最好的方法吗?

string void fn(string sz, data d, eventhdl nextFunc)
{
    //do stuff
    if(nextFunc == null)
        return ret;
    else
        return nextFunc(ret, d, nextFunc.Next);
}

5 个答案:

答案 0 :(得分:2)

你在找这样的东西吗?

T Foo<T>(T seed, IEnumerable<Func<T, T>> funcs)
{
    T current = seed;

    foreach (Func<T, T> func in funcs)
    {
        current = func(current);
    }

    return current;
}

用法:

int result = Foo<int>(1, new Func<int, int>[]
             {
                 i => i + 1,
                 i => i * 2,
                 i => i * i
             });

// result is 16

答案 1 :(得分:1)

考虑使用流畅的界面创建一个类ComboFunc,这样你就可以......

var fn = new ComboFunc()。A(“arg1”)。B(“arg2”)。C(“arg3”); var result = fn.Apply(“arg4”);

类ComboFunc上的流畅接口可用于在内部构建函数链,然后执行该函数链。例如,B()会将函数b()链接到内部的Func链上并返回一个新的ComboFunc()对象。

这给了你 (a)清晰的语法; (b)能够指定约束 AT DESIGN TIME 的规则,可以在其他人之上调用哪些函数(通过返回不同的类型。

像...一样的东西。

    public abstract class ComboFuncBase
    {
        protected Func<string,string> chain = x => x;     // start with identity operation

        // Here are your various functions ... defined as methods or as functions like this ..
        protected Func<string, string> Afunc = input => input + "A";
        protected Func<string, string> Bfunc = input => input + "B";
        protected Func<string, string> Cfunc = input => input + "C";

        /// <summary>
        /// Execute the chain of functions
        /// </summary>
        public string Apply(string argument)
        {
            return chain(argument);
        }

        /// <summary>
        /// Apply FunctionC - always available
        /// </summary>
        public ComboFuncWithC C(string sz)
        {
            return new ComboFuncWithC() { chain = x => Cfunc(chain(x)) };
        }

    }

    /// <summary>
    /// A chain without a C in it yet allows A's and B's
    /// </summary>
    public class ComboFunc : ComboFuncBase
    {
        /// <summary>
        /// Apply FunctionA
        /// </summary>
        public ComboFunc A(string sz)
        {
            return new ComboFunc() { chain = x => Afunc(chain(x)) };
        }

        /// <summary>
        /// Apply FunctionB
        /// </summary>
        public ComboFunc B(string sz)
        {
            return new ComboFunc() { chain = x => Bfunc(chain(x)) };
        }
    }

    /// <summary>
    /// After C has been applied you can't apply A or B
    /// </summary>
    public class ComboFuncWithC : ComboFuncBase
    {
    }


    static void Main(string[] args)
    {
        string input = "hello";

        var combo = new ComboFunc().A(" world").B("!").C(" - see");

        // Intellisense / Compiler will not allow this ...
        //var combo2 = new ComboFuncBase.ComboFunc().A(" world").C("!").B(" - see");

答案 2 :(得分:1)

您需要多种方法才能参与单个请求。订单很重要。我想你的问题可能会有Decorator模式。但是,很难说从实施开始向后工作。如果您尝试将请求路由到右侧函数,则可能是Chain of Responsibility

答案 3 :(得分:0)

using System;
using System.Collections.Generic;

namespace FunctionCaller
{
    class Demo
    {
        private class data { }

        delegate string OperationDelegate(string sz, data d, Queue<OperationDelegate> funcs);

        public void CallFunctions()
        {
            var funcs = new Queue<OperationDelegate>();
            funcs.Enqueue(fn1);
            funcs.Enqueue(fn2);
            funcs.Enqueue(fn3);
            data d = new data();
            string sz = "Start";

            string result = CallFuncChain(sz, d, funcs);

            Console.WriteLine(result);
        }

        private static string CallFuncChain(string sz, data d, Queue<OperationDelegate> funcs)
        {
            if (funcs.Count > 0)
            {
                OperationDelegate nextFunc = funcs.Dequeue();
                sz = nextFunc(sz, d, funcs);
            }
            return sz;
        }

        string fn1(string sz, data d, Queue<OperationDelegate> funcs)
        {
            string ret = sz + "\r\nfn1";
            ret = CallFuncChain(ret, d, funcs);
            return ret;
        }

        string fn2(string sz, data d, Queue<OperationDelegate> funcs)
        {
            string ret = sz + "\r\nfn2";
            ret = CallFuncChain(ret, d, funcs);
            return ret;
        }

        string fn3(string sz, data d, Queue<OperationDelegate> funcs)
        {
            string ret = sz + "\r\nfn3";
            ret = CallFuncChain(ret, d, funcs);
            return ret;
        }
    }
}

答案 4 :(得分:0)

好的,如果您不想使用自己的CallFuncChain,可以使用Linq替代。

using System;
using System.Linq;

namespace FunctionCaller
{
    class Demo2
    {
        private class data { }

        public void CallFunctions()
        {
            var funcs = new Func<string, data, string>[] { 
                fn1, fn2, fn3
            };

            data d = new data();

            string sz1 = "Start";

            string result = funcs.Aggregate(
                sz1,
                (sz, x) => x(sz, d)
            );

            Console.WriteLine(result);
        }

        string fn1(string sz, data d)
        {
            return sz + "\r\nfn1";
        }


        string fn2(string sz, data d)
        {
            return sz + "\r\nfn2";
        }

        string fn3(string sz, data d)
        {
            return sz + "\r\nfn3";
        }
    }
}

我对此感到有点不安,虽然它很干净...... Linq让我们做了很多功能,我有时认为“应该”用对象来完成。